Linking with a dll compiles, but causes a segfault

2019-01-29 13:44发布

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.

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:

In the library, the header:

class FirstClass
{
public:
  static const char *FIRST_CLASS_NAME;
}

and the cpp file:

const char *FirstClass::FIRST_CLASS_NAME = "FIRST_CLASS";

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;

then if linked to a .dll it will segfault, but if linked to a .lib, it will output

FIRST_CLASS

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.

1条回答
男人必须洒脱
2楼-- · 2019-01-29 14:40

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.

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
{ ... };

Defining the symbol _DLL as appropriate in the respective projects. Visual Studio predefines _DLL when you create a new dll project.

There is no need for .def files in most cases these days.

查看更多
登录 后发表回答