我正在开发一个跨平台的Firebreath插件,它在Windows上崩溃了。我使用一个静态库,其中包含引用boost.asio的类。当我将该库与插件dll链接时,我会在与io_service子系统交互时(即,在套接字构建过程中)观察到崩溃。当我将静态库与普通可执行文件链接时,问题不会而发生。当我将静态库的内容直接编译到插件dll项目中时,崩溃不会发生。我竭尽全力确保我在Windows上构建环境的各个方面都是一致的(构建模式、Visual Studio版本等)。此外,我还对boost.asio标头进行了防火墙保护,因此插件dll代码对boost.asio子系统没有可见性(不幸的是,对vs2008和vs2010没有影响)。据我所知,我已经尽了一切可能确保构建环境表现良好,但问题仍然存在。
社区能否就可能暴露或解决问题的潜在风险或方法提供任何建议?
链接静态库与加载DLL之间有两个显著不同的地方:
-
全局初始化:在DLL中,它们都运行。在静态库中,链接器只有在满足某些未解析的外部条件时才会引入对象文件,因此依赖于使用全局对象的构造函数或初始化表达式注册自己的组件的系统会失败。
-
共享CRT:在静态库中,对标准库的所有调用都在链接时间内解析,主应用程序和库函数都调用标准库的同一副本。在DLL中,您有可能拥有标准库的两个副本,如果您小心不要在库和应用程序之间共享任何标准库对象(如
FILE*
、std::string
,甚至malloc
/free
对),这可能是可以的。
第二件事很可能是咬你的东西。有一种懒惰的方法可以修复它:使用标准库DLL,还有一种更好的方法可以解决它:计算内存和对象的生存期,不要试图在一侧分配而在另一侧释放,或者跨边界共享C++类布局。虚拟功能可以很好地跨越边界。
"更好"方式的优点是,插件可以在任何版本的编译器中构建,这对于开发周期后期的维护来说都是一件大事。
在FireBreath插件准备脚本中,尝试打开WITH_DYNAMIC_MSVC_RUNTIME标志。