【问题标题】:Static variables with build-in types in C++ DLL is not initializedC++ DLL 中具有内置类型的静态变量未初始化
【发布时间】:2014-04-27 05:51:19
【问题描述】:

我需要从依赖于一些全局静态变量的 C++ 代码构建 DLL 库。用户定义类的静态变量初始化得很好,而原始类型(int)的变量则没有。更有什者,试图改变这些变量的值会导致内存错误。我做错了什么?

我能够在几行示例中复制此错误,这是我的代码:

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

输出:

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

我知道类似的问题:Loading DLL not initializing static C++ classes 并在链接选项中添加“-entry:_DllMainCRTStartup”并不能解决此问题。

我也知道在 C++ 中初始化单例的正确方法,但是对于这个项目,我需要移植相当大的 Linux 项目并且修改/重构它是不切实际的。

谢谢!

【问题讨论】:

  • 您是否尝试过在没有 def 文件的情况下使用 dllexport 和 dllimport?
  • 通过demangler.com 运行导出让我感谢该函数预计不会返回一个int&,而是一个int。 403973631是否可能是内存位置而不是值?
  • @cup 我试过使用 dllexport ,这确实解决了问题。但是我不能在我的项目中使用这个解决方案,因为它需要我修改原始代码库。知道如何创建正确的 def 文件吗?
  • @gha.st 我相信导出行正在为 static_int_ 变量指定导出,因此是正确的(函数本身是内联的)
  • 在 Windows 上,您不能跨 DLL 边界使用 C++ 功能。您可以在程序中使用 C++,也可以在应用程序中使用 C++,但每个都有自己完全独立的 C++。这与 Linux 非常不同,Linux 有一个由所有模块共享的系统 C++ 运行时。如果您有一个带有 C++ API 的库,请使用静态链接。

标签: c++ windows dll


【解决方案1】:

使用 def 文件并不是最好的方法 - 您应该使用 dllexport 来避免痛苦。

如果您必须使用 def 文件,因为它已被指定,请将您的 def 文件更改为

LIBRARY mylib
EXPORTS
   ?get_static_int@AAA@@SAAAHXZ

正如您所发现的,该函数是内联的,因此您需要取消内联它。您可以在 cl 行上使用 /Ob0 ,但我从来没有发现它可以工作。它仍然被内联,你仍然会得到异常。 mylib.hpp 应该是

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

将以下内容添加到 mylib.cpp

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

如果你这样做,那么它应该在不抛出异常的情况下运行。

【讨论】:

  • 谢谢,让函数非内联确实解决了问题!
  • 另一种选择是不使用 DLL。只需将其用作静态库即可。这样,您就不需要 def 文件了。
猜你喜欢
  • 1970-01-01
  • 2011-07-04
  • 1970-01-01
  • 2011-06-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多