我正在用 C++ 编写一个 Windows DLL。该库只有 C 接口(interface),并且仅使用也有 C 接口(interface)的标准 Windows 库。因此,将所有 C++ 库静态链接到库中似乎是安全的,因为仅使用 C 接口(interface)时,我不依赖于 C++ ABI 版本。
不幸的是,当我使用 -static-stdc++ -static-libgcc 编译库时,我的库停止处理异常,并且当引发某些异常时,DLL 调用其静态链接的 _Unwind_RaiseException
中止整个应用程序的函数。
我认为它可能是一个损坏的libgtcc.a
,所以我尝试更新我的编译器。但 MinGW 4.8 和 MinGW 6.3 的结果是相同的。
请问有人可以向我解释一下这里到底发生了什么吗?
克拉西克
最佳答案
您是否处理了 DLL 内的所有异常?如果任何异常“泄漏”到具有 C 调用约定的函数之外,就会导致应用程序崩溃。
在使用静态 libstdc++ 的 MinGW x86_64-5.3.0-win32-seh-rt_v4-rev0 和 mingw32 4.8.1 dwarf2 下,我对 C++ 异常没有任何问题/libgcc。
DLL 源代码 (dll.cpp
):
#include <windows.h>
#include <exception>
#include <iostream>
extern "C" {
__declspec(dllexport) int __stdcall test() {
try {
new int[-1];
return 123;
} catch (const std::exception& ex) {
std::cerr << "Exception:" << ex.what() << std::endl;
return 456;
}
}
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
return TRUE;
}
应用程序源(app.c
):
#include <stdio.h>
#ifdef __cplusplus
extern "C"
#endif
__declspec(dllimport) int __stdcall test();
int main() {
printf("result: %d\n", test());
return 0;
}
编译:
g++ -O2 -static-libgcc -static-libstdc++ -shared -Wl,--out-implib=dtest.lib -s -o dtest.dll dll.cpp
g++ -O2 -static-libgcc -static-libstdc++ -L。 -s -o app app.c -ldtest
输出:
Exception:std::bad_alloc
result: 456
为了回答您的评论“为什么我需要支持 SEH 的编译器?我认为 SEH 允许我捕获 Windows 异常” - 在 Windows 上,SEH 是所有的事实上的标准异常,包括 C++ 异常(使用 Visual C++ 编译时)。 MinGW 对 C++ 异常有不同的实现(SEH、SJLJ 和 DWARF),但是 SEH 是唯一零开销的机制,因此如果它可用,您确实应该更喜欢它而不是 SJLJ 和 DWARF。
关于c++ - Windows DLL 上的静态链接 libgcc,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42159583/