0

I need to build DLL lib from C++ code which rely on some global static variables. Static variables of user defined classes initialized just fine while variables with primitive types (int) does not. Even more, attempt to change value of such variables lead to memory errors. What am I doing wrong?

I was able to replicate this error in a few lines example, here is my code:

mylib.hpp

#include <string>

class AAA
{
public:
    static int             & get_static_int() { return static_int_; }
private:
    static int               static_int_;
};

mylib.cpp

#include "mylib.hpp"
#include <iostream>
int               AAA::static_int_          = 42;
class BBB
{
public:
    BBB() { std::cout << "BBB constructor!!!" << std::endl; };
};
static BBB b;

mylib.def:

LIBRARY mylib
EXPORTS
   ?static_int_@AAA@@0HA

main.cpp

#include <mylib.hpp>
#include <iostream>
int main()
{
    std::cout << "get_static_int():" << AAA::get_static_int() << std::endl;
    AAA::get_static_int() = 10;  // Exception!
}

build.bat

cl /c mylib.cpp /I. /Fomylib.obj /MD /EHsc
link /MACHINE:X64 /dll mylib.obj /DEF:mylib.def /out:mylib.dll msvcrt.lib kernel32.lib oleaut32.lib
cl main.cpp mylib.lib /I. /EHsc /MD

output:

>main
BBB constructor!!!
get_static_int():403973631
<windows complain>

I am aware of similar question: Loading DLL not initializing static C++ classes and adding "-entry:_DllMainCRTStartup" to link options does not fix this problem.

I am also aware of proper way to initialize singletons in C++ but for this projects i need to port rather large Linux project and modifying/refactoring it will not be practical.

Thanks!

Community
  • 1
  • 1
WorkPerNap
  • 13
  • 4
  • Have you tried using dllexport and dllimport without the def file? – cup Apr 27 '14 at 06:28
  • Running your export through http://demangler.com/ leads me to thank that function is not expected to return an int&, but an int. Is it possible that 403973631 is the memory location instead of the value? – danielschemmel Apr 27 '14 at 07:21
  • @cup I have tried using dllexport and this is indeed solves the problem. But I can't use this solution in my project because it will require me to modify original codebase. Any idea how to create proper def file? – WorkPerNap Apr 27 '14 at 16:19
  • @gha.st I believe the export line is specifying export for static_int_ variable and therefor is correct (the function itself is inlined) – WorkPerNap Apr 27 '14 at 16:23
  • On Windows, you cannot use C++ features across DLL boundaries. You can use C++ in the program, and you can use C++ inside the application, but each has its own completely separate C++. This is very unlike Linux where there is a system C++ runtime shared by all modules. If you have a library with a C++ API, use static linking. – Ben Voigt Apr 28 '14 at 01:07
  • @BenVoigt I see... this is actually explains my original problem: i was trying to create DLL that uses other DLL which have static data. - Thank you! – WorkPerNap Apr 28 '14 at 01:42
  • oops, I meant for one of those "program" and "application" to be "DLL". – Ben Voigt Apr 28 '14 at 01:43

1 Answers1

0

Using a def file isn't the best way of doing this - you should save yourself the pain by using dllexport.

If you must use def files because it has been dictated, change your def file to

LIBRARY mylib
EXPORTS
   ?get_static_int@AAA@@SAAAHXZ

As you have discovered, the function is inlined so you need to uninline it. You could use /Ob0 on the cl line but I've never found that to work. It still gets inlined and you will still get the exception. mylib.hpp should be

class AAA
{
public:
static int             & get_static_int();
private:
static int               static_int_;
};

Add the following to mylib.cpp

int& AAA::get_static_int()
{
return static_int_;
}

If you do it this way, then it should run without throwing the exception.

cup
  • 7,589
  • 4
  • 19
  • 42