[英]EXC_BAD_ACCESS on throwing exception
我对我们的一位合作伙伴提供的共享库有疑问,并将其范围缩小到此测试用例:
我自己的测试库编译为libCrashTestLib.dylib
:
#include <exception>
#include <iostream>
extern "C" void Test() {
try {
throw std::exception{};
} catch (const std::exception& e) { }
std::cout << "Success" << std::endl;
}
我的主要可执行文件会加载我的库并调用Test
函数:
#include <string>
#include <dlfcn.h>
int main(int argc, char** argv) {
std::string lib_path = "/path/to/libCrashTestLib.dylib";
void* handle = dlopen(lib_path.c_str(), RTLD_NOW | RTLD_GLOBAL);
void (*test_pointer)() = reinterpret_cast<void(*)()>(dlsym(handle, "Test"));
test_pointer();
dlclose(handle);
}
这可以正常工作并打印Success
。
但是,当我只是链接(甚至不调用)由我们合作伙伴提供的库时,它给了我EXC_BAD_ACCESS
,在其中抛出异常。
我要寻找的是两件事之一:
为了完整CMakeLists.txt
,这是我正在使用的CMakeLists.txt
:
cmake_minimum_required(VERSION 3.0)
project(CrashTest CXX)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED on)
find_library(VendorApi NAMES vendorapi PATHS ${CMAKE_SOURCE_DIR})
add_library(CrashTestLib SHARED lib.cpp)
# Uncomment this line to make it crash:
#target_link_libraries(CrashTestLib VendorApi)
add_executable(CrashTestMain main.cpp)
崩溃的最可能原因是使用libstdc++
编译了供应商的库,而使用libc++
编译了您的代码。
我可以很轻松地通过在构建类时发出cout来触发崩溃,这是库加载时的一部分,例如
#include <exception>
#include <iostream>
#include <string>
class bongo {
public:
bongo() {
std::cout << "Log something" << std::endl;
}
};
static class bongo *boing;
void __attribute__((constructor)) start_something(void) {
boing = new bongo;
}
extern "C" void Test() {
try {
throw std::exception{};
} catch (const std::exception& e) { }
std::cout << "Success" << std::endl;
}
加载程序代码:
#include <string>
#include <dlfcn.h>
int main(int argc, char** argv) {
std::string lib_path = "./libCrashTestLib.dylib";
void* handle = dlopen(lib_path.c_str(), RTLD_NOW | RTLD_GLOBAL);
void (*test_pointer)() = reinterpret_cast<void(*)()>(dlsym(handle, "Test"));
test_pointer();
dlclose(handle);
}
Makefile文件:
CXXFLAGS += -std=c++11
STDLIB = -stdlib=libstdc++
all: libCrashTestLib.dylib testLib
libCrashTestLib.dylib: CrashTest.cpp
$(CXX) $(CXXFLAGS) $(STDLIB) -shared -o $@ $<
testLib: testLib.cpp
$(CXX) $(CXXFLAGS) -o $@ $<
clean:
rm -f *.dylib testLib
调用:
$ make clean && make STDLIB= && ./testLib
rm -f *.dylib testLib
c++ -std=c++11 -shared -o libCrashTestLib.dylib CrashTest.cpp
c++ -std=c++11 -o testLib testLib.cpp
Log something
Success
调用失败:
$ make clean && make && ./testLib
rm -f *.dylib testLib
c++ -std=c++11 -stdlib=libstdc++ -shared -o libCrashTestLib.dylib CrashTest.cpp
c++ -std=c++11 -o testLib testLib.cpp
Segmentation fault: 11
您可以使用otool -L
检查哪个版本的C ++库链接到二进制文件:
$ otool -L libCrashTestLib.dylib
libCrashTestLib.dylib:
libCrashTestLib.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 104.1.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.