android / ndk

The Android Native Development Kit
1.98k stars 257 forks source link

Compile errors with malloc after switching from r15 to r17 #738

Closed benstadin closed 6 years ago

benstadin commented 6 years ago

I just switched from NDK 15 to the one installed with Android Studio (which is currently 17). But now malloc and friends is not found, even though stdlib.h is included.

I've looked everywhere, but found no solution so far. My base class is in c++, which uses a C library. I think this might be relevant. below is the console output.

EDIT: I've removed everything from the C++ class. So it's just an entirely empty C++ file, and a header file. The problem here seems to be in mixing C++ and C with CMAKE with NDK - which is really odd. As an example, the below error for missing malloc/free is thrown when just is included. Thereby ruling out that my own includes are somehow messing things up. Example DeepMapSQL.hppp file:

#ifndef DeepMapSQL_hpp
#define DeepMapSQL_hpp

#include <string>
#include <list>
#include <stdio.h>

#endif /* DeepMapSQL_hpp */

Build log:

    In file included from ../../../../../../../hdm-deepmap-sql/dms/hdm-deepmap-sql/include/dms/DeepMapSQL.hpp:13:
    In file included from /Users/ben/Library/Android/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/include/string:470:
    In file included from /Users/ben/Library/Android/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/include/string_view:169:
    In file included from /Users/ben/Library/Android/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/include/__string:56:
    In file included from /Users/ben/Library/Android/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/include/algorithm:643:
    In file included from /Users/ben/Library/Android/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/include/memory:644:
    In file included from /Users/ben/Library/Android/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/include/typeinfo:61:
    In file included from /Users/ben/Library/Android/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/include/exception:82:
    /Users/ben/Library/Android/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/include/cstdlib:125:9: error: no member named 'calloc' in the global namespace
    using ::calloc;
          ~~^
    /Users/ben/Library/Android/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/include/cstdlib:126:9: error: no member named 'free' in the global namespace
    using ::free;
          ~~^
    /Users/ben/Library/Android/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/include/cstdlib:127:9: error: no member named 'malloc' in the global namespace
    using ::malloc;
          ~~^
    /Users/ben/Library/Android/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/include/cstdlib:128:9: error: no member named 'realloc' in the global namespace
    using ::realloc;
          ~~^
    4 errors generated.
    ninja: build stopped: subcommand failed.

In addition, this is the CMake file for the library:

    cmake_minimum_required(VERSION 3.6)
    include(../../toolchain/macros.cmake)

    project(hdmsql)

    set(HDM_SQL_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/dms/hdm-deepmap-sql)

    file(GLOB_RECURSE SOURCES
        ${HDM_SQL_SRC_DIR}/*.c
        ${HDM_SQL_SRC_DIR}/*.cpp
    )

    list(REMOVE_ITEM SOURCES ${HDM_SQL_SRC_DIR}/src/treeview.c)

    add_library(hdmsql STATIC
                ${SOURCES}
                )

    target_link_libraries(hdmsql hdmmaputils)
    target_include_directories(hdmsql PUBLIC ${HDM_SQL_SRC_DIR}/include/dms/)
    target_include_directories(hdmsql PRIVATE ${HDM_SQL_SRC_DIR}/src/)

    #############

    configure_file(${HDM_SQL_SRC_DIR}/include/dms/DeepMapSQL.hpp "${CMAKE_CURRENT_BINARY_DIR}/DeepMapSQL.hpp")
    configure_file(${HDM_SQL_SRC_DIR}/include/dms/dms.h "${CMAKE_CURRENT_BINARY_DIR}/dms.h")
    configure_file(${HDM_SQL_SRC_DIR}/include/dms/geometry.h "${CMAKE_CURRENT_BINARY_DIR}/geometry.h")
    configure_file(${HDM_SQL_SRC_DIR}/include/dms/vdbeapi.h "${CMAKE_CURRENT_BINARY_DIR}/vdbeapi.h")

build.gradle:

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    repositories {
        maven {
            url  "http://dl.bintray.com/android/android-tools"
        }
        jcenter()
        mavenCentral()
        google()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.1.1'
    }
}

allprojects {
    repositories {
        jcenter()
        google()
    }
}

ext {
    minSdkVersion = 21
    targetSdkVersion = 27
    compileSdkVersion = 27
    buildToolsVersion = "27.0.3"
    supportLibVersion = "27.1.1"
}

task clean(type: Delete) {
    delete rootProject.buildDir
}
DanAlbert commented 6 years ago
target_include_directories(hdmsql PUBLIC ${HDM_SQL_SRC_DIR}/include/dms/)
target_include_directories(hdmsql PRIVATE ${HDM_SQL_SRC_DIR}/src/)

I don't suppose either of these directories has its own stdlib.h or anything like that?

My trivial example matching yours (the include pattern of string -> list -> stdio.h, though from the error trace I think only the #include <string> is the relevant part of your example) works fine for me.

I'll need either the failing compile command line or the preprocessed source in order to even guess at what else could be wrong.

benstadin commented 6 years ago

After further investigation, the project had indeed a malloc.h (from an altered version of SQLite). Though, it was included as a private header and included different named wrapper functions. This has never been an issue before (though the naming was bad of course).

The reproduce the issue it should be enough to have an empty malloc.h header. The issue was gone after renaming this file. But I still think this issue should not occur.

DanAlbert commented 6 years ago

Why should that work? The project has a malloc.h that is overriding the system's, and that malloc.h says there's no such thing as calloc, free, malloc, or realloc.

DanAlbert commented 6 years ago

FYI, it looks like the only reason the project previously worked with r15 is that it defaulted to gnustl instead of libc++, and gnustl's <string> doesn't include <cstdlib>. The following test case fails on both r15c and r19-canary:

// include/malloc.h
// empty

// foo.cpp
#include <cstdlib>
int main() { return 0; }
# CMakeLists.txt
cmake_minimum_required(VERSION 3.6.0)
add_executable(foo foo.cpp)
target_include_directories(foo PRIVATE include)
stephenhines commented 6 years ago

To be fair, malloc.h is not specified as an official header. However, most Linux implementations have a malloc.h as well. The reason that this works in those cases, though, is that both malloc.h and cstdlib.h declare these functions, at least for the Linux I am using. Thus picking up the wrong "empty" malloc.h is fine.

DanAlbert commented 6 years ago

Hmm. @enh: any reason we shouldn't pull the standard malloc decls out into <bits/malloc.h> that gets included by both <stdlib.h> and <malloc.h>?

enh commented 6 years ago

lots of code in our tree seems to assume that it can get memalign(3) from <stdlib.h>, so i'll probably chicken out and include that in the set, but otherwise i'll take the opportunity to clean up too so folks pulling in <stdlib.h> get less namespace pollution. (because apparently i haven't learned my lesson yet.)

enh commented 6 years ago

the more i played with this and the more i thought about, the more i think it's a bad idea. it disrupts existing users for a fairly theoretical problem. i'd want to see more than one (already fixed) case to motivate actually making this change...