简体   繁体   English

抛出异常时EXC_BAD_ACCESS

[英]EXC_BAD_ACCESS on throwing exception

I'm having a problem with a shared library provided by one of our partners and narrowed it down to this test case: 我对我们的一位合作伙伴提供的共享库有疑问,并将其范围缩小到此测试用例:

My own test library compiled to libCrashTestLib.dylib : 自己的测试库编译为libCrashTestLib.dylib

#include <exception>
#include <iostream>

extern "C" void Test() {
  try {
    throw std::exception{};
  } catch (const std::exception& e) { }
  std::cout << "Success" << std::endl;
}

My main executable loads my library and calls the Test function: 我的主要可执行文件会加载我的库并调用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);
}

This works fine and prints Success . 这可以正常工作并打印Success

However, when I just link (not even call) the library provided by our partner it gives me an EXC_BAD_ACCESS where I throw the exception. 但是,当我只是链接(甚至不调用)由我们合作伙伴提供的库时,它给了我EXC_BAD_ACCESS ,在其中抛出异常。

What I'm looking for is either of two things: 我要寻找的是两件事之一:

  • A compiler or linker switch that helps me to get rid of this behavior. 可以帮助我摆脱这种行为的编译器或链接器开关。
  • A way to create my own library that crashes this program when I link it, so that I can give our partner more details what thay need to modify. 一种创建自己的库的方法,当我链接该程序时,它会使该程序崩溃,因此我可以为我们的合作伙伴提供更多详细信息,说明需要修改的内容。

For completeness, here is the CMakeLists.txt I'm using: 为了完整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)

The most likely reason for the crash is that the vendor's library is compiled with libstdc++ , while your code is compliled with libc++ . 崩溃的最可能原因是使用libstdc++编译了供应商的库,而使用libc++编译了您的代码。

I can trigger a crash quite easily by issuing a cout while constructing a class as part of the library load-time eg 我可以很轻松地通过在构建类时发出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;
}

loader code: 加载程序代码:

#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: 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

Invocation: 调用:

$ 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

Failing invocation: 调用失败:

$ 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

You can check what version of the C++ library is linked to the binary using otool -L : 您可以使用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM