我在尝试使用Android 23 (23.1.7779620)构建一个简单的C++库时感到非常困惑。我正在使用CMake,这是一个非常简单的程序:
# CMakeLists.txt
cmake_minimum_required(VERSION 3.14)
project(mf)
add_library(mf lib.cpp)
// lib.hpp
#pragma once
#include <string>
std::string foo(std::string);
// lib.cpp
#include "lib.hpp"
std::string foo(std::string str) {
return std::string{"test"} + str;
}这是要构建的命令行:
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DANDROID_STL=c++_shared -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=android-29 -DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake ..
cmake --build . -vlibc++.so,而不是libc++_shared.so。他们之间有什么区别?我读过这篇文章。但是还没有解释libc++和libc++_shared之间的区别。std::__1下,但我找不到类似的东西。我知道使用libc++_shared是因为这个命令:
$ readelf -d libmf.so
Dynamic section at offset 0x76e0 contains 26 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libm.so]
0x0000000000000001 (NEEDED) Shared library: [libc++_shared.so]
0x0000000000000001 (NEEDED) Shared library: [libdl.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so]
0x000000000000000e (SONAME) Library soname: [libmf.so]运行nm似乎使用了来自libstdc++的符号
$ nm -gDC libmf.so | grep '__ndk1'
0000000000003af0 T foo(std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >)
U std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >::append(char const*, unsigned long)
$ nm -gDC libmf.so | grep '__1'
$更新
在这篇文章中解释了libc++.so和libc++_shared.so的区别。
发布于 2021-11-30 10:05:25
通过将-DANDROID_STL=c++_shared传递给CMake调用,您将显式地请求共享运行时,而不是默认运行时。
正如在文献资料中所解释的,规则很简单:
规则的基本原理很简单: C++运行时具有某些全局数据结构,必须初始化一次,并且只能在内存中存在一次。如果您意外地加载了两个库,它们都静态地链接了C++运行时,那么您就有(例如)两个冲突的内存分配器。当您通过其他库分配free或delete内存时,或者如果您跨库边界传递C++ STL对象(如std::string ),这将导致崩溃。
为了完整起见,在较旧的NDK中,libstdc++ ( GNU C++运行时)也包含在NDK中,但NDK r18不再是这种情况。
https://stackoverflow.com/questions/70166739
复制相似问题