0

我有一个静态类成员

class bar {...}

class foo {
    public:
        static QHash<qint64,bar>* barRepHash;
}

现在我调用一个在共享库中访问该成员的函数,我得到一个内存错误,而当我通过主程序访问该函数时,它工作正常。我已经在多种情况下对此进行了测试。

我在主应用程序中初始化了变量,但我没有在共享库中再次初始化它(这似乎没有必要)。

我在 Ubuntu 中使用 GCC 和 QT。

发生了什么,我该如何解决?

4

2 回答 2

1

IIRC exe 和共享库将获得它们自己的静态成员变量副本,因此您需要在每种情况下单独初始化它。

由于它是一个指针,因此一种方法可能是在您的主程序中正常初始化它,然后在加载它时将指针传递给 dll,以便可以将 dll 的版本设置为指向与 exe 版本相同的位置。

编辑:好的,我做了一些测试(Windows,VC9),看起来全局变量和静态变量(无论是函数、类还是其他)都是每个模块的(即每个 exe 和 dll 都会得到它自己的副本,即使该变量来自一个共同的来源,比如一个静态库)。

我将测试该类上的 dllimport/export 是否使它们使用通用副本。

编辑2:

好的,在 dll 中使用 __declspec(dllexport) 并在 exe 中使用 __declspec(dllimport) (使用预处理器宏在它们之间切换,具体取决于包含头文件的内容),因为静态变量声明使静态变量对两个模块都通用。它也适用于全局变量,我将假设静态函数变量。

#pragma once

//defined when compiling test.dll
#ifdef TEST_EXPORTS
#define DLL __declspec(dllexport)
#else
#define DLL __declspec(dllimport)
#endif

//foo and bar definition in test.cpp, ie only in the dll's compile
class X
{
public:
    static int foo;
};
DLL extern int bar;

然而,AFAIK GCC 没有 dllexport 和 dllimport,但是在创建共享库(无论是 dll 左右)时,它可能有一些其他方式来实现相同的效果。

如果没有,那么我能想到的唯一其他解决方案就是我最初建议的解决方案。在 exe 中初始化你的静态指针,然后在 dll 中有一个函数来设置静态变量,exe 可以调用它来传递它的指针副本。

于 2009-12-05T11:17:07.187 回答
0

通过使用“节”属性可以放置在数据和 bss 之外的特定节上。只有在 Windows 中,这些部分才能通过使用“共享”属性跨可执行文件共享。在其他平台中,不支持此功能。因此,解决方案将如上一个答案中所述。

于 2010-01-08T13:37:07.930 回答