当代码链接到 exe 时 C++ 程序崩溃,但当代码编译成 exe 时工作正常,这是怎么回事?

标签 c++ compilation linker

我有一个程序在一个平台上运行了很长时间。由于它的成功,它将被移植到另一个平台。没问题,我想因为它是用标准 C++ 编写的...

我的方法(用伪 CMake 说明):

  • 通过采购平台特定的工具链来设置开发环境,以确保目标平台正确
  • 将所有核心业务逻辑分解到一个应用程序对象中,并从中构建一个库(来自相同源代码的每个平台一个库):

    add_library(appLib STATIC app.cpp)
    target_link_libraries(appLib utilLib networkLib dbLib ${boostLibs})
  • 有一个main_a.cpp和另一个main_b.cpp,分别对平台a和b进行平台相关的初始化,让其中的main函数实例化应用对象。

    int main()
    {
        auto result = initAndDoPlatformStuff();
        App app(result);
        app.run();
    }
  • 指示编译器和链接器组装可执行文件:

    if (Platform_A)
    add_executable(appExe main_a.cpp)
    else()
    add_executable(appExe main_b.cpp)
    endif()
    target_link_libraries(appExe appLib)

原则上,我认为这是一种完全有效的方法。但实际上这是行不通的。在第二个程序崩溃时,几乎每次崩溃都不同;检查核心转储表明它有时在标准库中崩溃,有时在 boost 库中以及在我的代码中崩溃,但我猜这是无稽之谈。程序似乎可以运行 10 次,但最终会崩溃。

但是,如果我使用完全相同的代码,只需将其提取到其原始 main.cpp 文件中,然后以不同的方式将其构建在一起,如下所示:

int main()
{
    auto result = initAndDoStuff();
    processForever(result); // Business logic
}
add_executable(appExe main.cpp)
target_link_libraries(appExe utilLib networkLib dbLib ${boostLibs})

然后就可以了!

我很困惑也很困惑。我怀疑它与代码布局有关,因此我尝试了 PIC 和 PIE 的不同变体,但没有成功。是否有任何工具可以让您全面了解二进制代码布局?我知道 nm、od、objdump,但它们是低级的,我不知道要寻找什么...... 也许我走错了路,也许问题与完全不同的事情有关。有没有人预感到什么会导致这种行为?我还能如何解决这个问题?

最佳答案

其实,错在我。当然... 我在将代码重构为lib时确实试图将所有细节都正确无误,但显然我不够细心,在寻找问题时盲目。
我最终发现的问题是,我在重构后仍然将一个变量保留为局部变量,然后超出范围导致引用释放的内存,从而导致各种未定义的行为。

关于当代码链接到 exe 时 C++ 程序崩溃,但当代码编译成 exe 时工作正常,这是怎么回事?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56460040/

相关文章:

c++ - g++ 对构造函数的 undefined reference

linux - 如何链接共享库的特定名称(版本)

ubuntu - 无法链接到 libglew 或 libglfw

c++ - QT 标签 setText() 同时保留文本格式

c++ - 如何为网格生成随机位置?

c++ - 是否有隐式模板<typename T>运算符<<(const ostream&,T)?

c++ - 从字符串转换为 byte[] 并将结果添加到内存流中

java - 您通常会在共享 java 文件之前编译它吗?

c++ - sublime text C++ 编译导致段错误

audio - 如何编译 VST 插件?