与 dll 链接可以编译,但会导致段错误
我一直致力于使用 Visual Studio 2015 编译大量最初为在 linux 上使用而编写的代码文件,使用 g++.具体来说,我需要一个 .dll 用于另一个程序.不幸的是,我遇到了很多问题.
I've been working on compiling with Visual Studio 2015 a large number of code files written originally for use on linux, using g++. Specifically, I need a .dll for use with another program. Unfortunately, I have run into a number of problems.
在做了一些研究之后,我尝试将 __declspec(dllexport) 添加到头文件中.这有助于解决一些编译错误,但不适用于静态成员函数和变量.然后我制作了一个 .def 文件,它消除了编译过程中剩余的错误,但是在运行一些同时编译的测试(并使用相同的编译器)时,其中许多测试由于段错误而失败.如果我将其构建为 .lib,或者如果我将测试直接链接到各种目标文件,这些相同的测试会成功,但对于最终程序,我需要一个 .dll(使用 g++ 的原始构建构建一个 .so).我一直找不到其他有类似问题的人.
After doing some research, I tried adding __declspec(dllexport) to the header files. This helped with some of the compilation errors, but didn't work for the static member functions and variables. I then made a .def file, which got rid of the remaining errors in compilation, but upon running some of the tests compiled at the same time (and with the same compiler), many of them failed due to segfaults. These same tests succeed if I build it as a .lib, or if I link the tests directly to various object files, but for the final program I need a .dll (The original build using g++ builds a .so). I have been unable to find anyone else with a problem similar to this.
这里是一些代码的简化版本,我发现这些代码与会导致段错误的行之一相关:
Here is a simplified version of some of the code which I have found to be relevant to one of the lines which will cause a segfault:
在库中,标题:
class FirstClass
{
public:
static const char *FIRST_CLASS_NAME;
}
和cpp文件:
const char *FirstClass::FIRST_CLASS_NAME = "FIRST_CLASS";
测试文件中引用此变量的任何内容都将导致 .dll 段错误.具体来说,如果我有这条线
Anything in the test file which references this variable will cause a segfault with a .dll. Specifically, if I have the line
std::cout << FirstClass::FIRST_CLASS_NAME << std::endl;
然后如果链接到 .dll 它将出现段错误,但如果链接到 .lib,它将输出
then if linked to a .dll it will segfault, but if linked to a .lib, it will output
FIRST_CLASS
由于这是一个更多地编译其他人创建的大量代码的项目(我并不了解所有这些,对 C++ 相当陌生),我宁愿不必对源代码本身进行太多编辑,但似乎应该更多地与
As this is a project more to compile a large amount of code created by others (not all of which I understand, being rather new to c++), I would rather not have to do very much editing of the source code itself, but it seems like it should be more to do with
如果您能帮助理解这里发生的事情,我们将不胜感激.
Any help in understanding what's going on here would be much appreciated.
推荐答案
dll 中的静态数据位于不同的地址空间中,因此您无法直接引用它(调用必须通过导入表进行映射).当您链接静态库时,所有内容都在可执行文件的地址空间中,因此您可以这样做.
The static data in the dll is in a different address space so you can't directly reference it (the call has to be mapped thru an import table). When you link a static library everything is in the address space of the executable so you can.
您必须成对使用 dllexport 和 dllimport.dllexport 是您在共享库 (dll) 中定义它们的地方,而 dllimport 是您在应用程序中使用它们的地方.您通常会有一个宏,它的计算结果为 __declspec(dllexport) 或 __declspec(dllimport),具体取决于它的使用位置.例如
You must use dllexport and dllimport as a pair. dllexport where you define them in the shared library (dll) and dllimport where you use them in the application. You'll typically have a macro that evaluates to either __declspec(dllexport) or __declspec(dllimport) depending on where it's used. E.g.
#ifdef _DLL // inside the DLL
#define DLLExportImport __declspec(dllexport)
#else // outside the DLL
#define DLLExportImport __declspec(dllimport)
#endif
并在定义类的地方使用它:
And use it where you define the class:
class DLLExportImport FirstClass
{ ... };
在相应的项目中根据需要定义符号 _DLL
.Visual Studio 在您创建新的 dll 项目时预定义 _DLL
.
Defining the symbol _DLL
as appropriate in the respective projects. Visual Studio predefines _DLL
when you create a new dll project.
如今在大多数情况下都不需要 .def 文件.
There is no need for .def files in most cases these days.
相关文章