问题与优化无关,而是与静态库中的符号链接器如何链接有关。
然而,当代码编译成静态库时,将该库链接到可执行文件中时,这些静态对象永远不会被构建,因此类不会向工厂注册,工厂也就无法创建任何东西。
这是因为没有其他变量引用该注册变量。因此,链接器不会从存档中提取符号定义。
要告诉Unix链接器即使没有其他内容引用它也要保留该注册变量,在链接到该静态库时使用
-Wl,--undefined=<symbol>
编译器开关:
-u symbol
--undefined=symbol
强制在输出文件中将symbol输入为未定义符号。这样做可能会触发从标准库链接其他模块。可以重复使用带有不同选项参数的-u以输入其他未定义符号。
如果该注册变量具有“C”连接,则
<symbol>
是变量名。
对于C ++连接,您需要使用
nm --defined-only <object-file>
查找搅拌名称。您还可能需要将该变量放入命名空间中,以使其具有外部链接。
示例:
[max@supernova:~/src/test] $ cat mylib.cc
#include <cstdio>
namespace mylib {
struct Register
{
Register() { std::printf("%s\n", __PRETTY_FUNCTION__); }
};
Register register_me;
}
[max@supernova:~/src/test] $ cat test.cc
#include <iostream>
int main() {
std::cout << "Hello, world!\n";
}
[max@supernova:~/src/test] $ make
mkdir /home/max/src/test/debug
g++ -c -o /home/max/src/test/debug/test.o -MD -MP -std=gnu++14 -march=native -pthread -W{all,extra,error,inline} -ggdb -fmessage-length=0 -Og test.cc
g++ -c -o /home/max/src/test/debug/mylib.o -MD -MP -std=gnu++14 -march=native -pthread -W{all,extra,error,inline} -ggdb -fmessage-length=0 -Og mylib.cc
ar rcsT /home/max/src/test/debug/libmylib.a /home/max/src/test/debug/mylib.o
g++ -o /home/max/src/test/debug/test -ggdb -pthread /home/max/src/test/debug/test.o /home/max/src/test/debug/libmylib.a
[max@supernova:~/src/test] $ ./debug/test
Hello, world! <-------- Missing output from mylib::register_me.
[max@supernova:~/src/test] $ nm --defined-only -C debug/mylib.o
0000000000000044 t _GLOBAL__sub_I__ZN5mylib11register_meE
0000000000000000 t __static_initialization_and_destruction_0(int, int)
0000000000000000 B mylib::register_me <-------- Need a mangled name for this.
0000000000000000 r mylib::Register::Register()::__PRETTY_FUNCTION__
[max@supernova:~/src/test] $ nm --defined-only debug/mylib.o
0000000000000044 t _GLOBAL__sub_I__ZN5mylib11register_meE
0000000000000000 t _Z41__static_initialization_and_destruction_0ii
0000000000000000 B _ZN5mylib11register_meE <-------- The mangled name for that.
0000000000000000 r _ZZN5mylib8RegisterC4EvE19__PRETTY_FUNCTION__
# Added -Wl,--undefined=_ZN5mylib11register_meE to Makefile.
[max@supernova:~/src/test] $ make
g++ -o /home/max/src/test/debug/test -ggdb -pthread -Wl,--undefined=_ZN5mylib11register_meE /home/max/src/test/debug/test.o /home/max/src/test/debug/libmylib.a
[max@supernova:~/src/test] $ ./debug/test
mylib::Register::Register() <-------- Output from mylib::register_me as expected.
Hello, world!
static
直到在该 CPP 文件中的某些代码被使用之前才会被构造。因此,如果从未调用 CPP 文件中的任何代码,则这些static
可能永远不会被构造。这与 Gcc 优化无关,这是 C++ 的工作原理。MSVC 是一个奇怪的例外,它忽略了这一点,在启动main
之前构造所有命名空间static
。 - Mooing Duck-Wl,--allow-multiple-definition
。 - tmm1