外部指针在静态库中为空,当不是静态库时工作正常

Extern pointer is null in static library, worked fine when not a static library

我将我的 Visual Studio 项目(2015,C++)分成三部分:

在我将其拆分为 lib/exe/tests 之前,主应用程序只是一个独立的可执行文件,并且运行良好。

现在我不能 运行 只有主函数的可执行文件,也不能进行单元测试,因为某个指针总是空的。唯一的主要区别是我在这个例子中使用了一个原始指针,但我在我的代码中使用了 unique_ptr (但是目前我切换到原始指针只是为了确保下面的例子与可能而且它并没有神奇地 compile/run 正确地使用原始指针)。

代码看起来与以下非常相似(多余的代码已被删除):

// console.hpp
extern Console *console;

实现cpp文件(仅需要的):

// console.cpp
Console *console = new Console();

现在在一些不相关的函数中,由于控制台指针是空指针,这段代码失败了:

// some_other_file.cpp
#include "console.hpp"

    // Inside some function...
    console->doSomething();  // console is NULL

同样,我的代码 在一个项目中工作得很好 。无论如何,即使它被分成 3 个部分,它都可以正常编译,没有链接错误,但现在指针总是空的。

作为最后一个有趣的说明,全局和外部的非指针变量确实有效。这是否仅限于 pointers/unique_ptrs?

单例模式可以解决这个问题吗?

线索在这条评论中:"it appears other code is getting called before the main function that don't let the global variable get initialized."

引用 console 的代码可能 运行ning 作为另一个全局初始化的一部分,在这种情况下,发生在 console 的初始化之前。您必须非常小心,以确保您不依赖于全局初始化程序的顺序。在拆分程序之前你可能很幸运,现在你的运气已经 运行。

修复它的最简单方法是使用单例模式。不是让程序的其他部分直接引用指针,而是让它们调用 returns 指针的函数,该函数将在第一次初始化它。这确保它在使用前被初始化。

这是一个常见的模式:

Console *GetConsole() {
    static Console *console = new Console();
    return console;
}

现在控制台不再是一个全局变量。所有想要访问控制台的东西都调用 GetConsole

函数局部静态变量将在第一次调用函数时被初始化,之后它只是 returns 的值。如果你有多个线程和一个较旧的编译器,你必须做更多的工作来防止可能的竞争条件。现代编译器应该以线程安全的方式进行初始化。