首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Windows DLL上的静态链接libgcc

Windows DLL上的静态链接libgcc
EN

Stack Overflow用户
提问于 2017-02-10 20:36:38
回答 2查看 2.4K关注 0票数 1

我正在用C++编写一个Windows DLL。这个库只有C接口,并且只使用标准的Windows库,这些库也有C接口。因此,将所有C++库静态链接到库中似乎是安全的,因为在仅使用C接口时,我不依赖于C++ ABI版本。

不幸的是,当我用-static-stdc++ -static-libgcc编译我的库时,我的库停止处理异常,当抛出一些异常时,DLL调用它的静态链接的_Unwind_RaiseException函数,从而中止整个应用程序。

我认为这可能是一个损坏的libgtcc.a,所以我尝试更新我的编译器。但是MinGW 4.8和MinGW 6.3的结果是一样的。

有人能给我解释一下这里到底发生了什么吗?

克拉西奇

EN

回答 2

Stack Overflow用户

发布于 2017-02-10 22:44:35

您是否正在处理DLL中的所有异常?如果任何异常在具有C语言调用约定的函数外部“泄漏”,它将使应用程序崩溃。

MinGW x86_64-5.3.0-win32-seh-rt_v4-rev0和带有静态libstdc++/libgcc的mingw32 4.8.1 dwarf2下,我没有遇到C++异常问题。

DLL源(dll.cpp):

代码语言:javascript
复制
#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):

代码语言:javascript
复制
#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

输出:

代码语言:javascript
复制
Exception:std::bad_alloc
result: 456

为了回答你的评论“为什么我需要支持SEH的编译器?我认为SEH可以让我捕获Windows异常”-在Windows上,SEH是所有异常的事实标准,包括C++异常(当用Visual C++编译时)。MinGW对C++异常有不同的实现( SEH,SJLJ和DWARF),但是SEH是唯一一种零开销的机制,所以如果它可用,你应该更喜欢它而不是SJLJ和DWARF。

票数 1
EN

Stack Overflow用户

发布于 2017-02-11 00:35:08

感谢RastyX在他的回答中提供了这个简单的例子。经过一些研究,我发现当我用-static-libgcc编译动态链接库部分和没有这个开关的应用程序部分时,应用程序崩溃(这两个部分都是用相同的g++编译的)。

也感谢Ripi2的TDM-GCC的建议。我尝试了SJLJ和DWARF-2异常处理,两者都有效。

总而言之,MinGW的libgcc似乎不喜欢每个进程被实例化一次以上。在我的例子中,我使用了一个在DLL中的副本(静态链接)和一个在应用程序中的副本,这可能会破坏异常处理。

另一方面,正如其网页所说,TDM-GCC专注于基本库的静态链接,因此即使没有-static-stdc++ -static-libgcc命令行开关,也可以生成仅依赖于Windows库的二进制文件(这就是我想要的)。此外,异常处理在这里也可以工作,所以更改工具链对我来说是正确的方式。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42159583

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档