【问题标题】:Static initialization and destruction of a static library's globals not happening with g++静态库的全局变量的静态初始化和销毁​​不会在 g++ 中发生
【发布时间】:2023-03-23 06:23:01
【问题描述】:

直到前一段时间,我还认为 .a 静态库只是 .o 对象文件的集合,只是将它们归档,而不是让它们以不同的方式处理。但是链接一个.o 对象和链接一个包含这个.o 对象的.a 静态库显然是不一样的。而且我不明白为什么...

让我们考虑以下源代码文件:

// main.cpp
#include <iostream>
int main(int argc, char* argv[]) {
    std::cout << "main" << std::endl;
}

// object.hpp
#include <iostream>
struct Object
{
    Object() { std::cout << "Object constructor called" << std::endl; }
    ~Object() { std::cout << "Object destructor called" << std::endl; }
};

// object.cpp
#include "object.hpp"
static Object gObject;

让我们编译并链接并运行这段代码:

g++ -Wall object.cpp main.cpp -o main1
./main1
> Object constructor called
> main
> Object destructor called

调用全局gObject对象的构造函数和析构函数。

现在让我们从我们的代码创建一个静态库并在另一个程序中使用(链接)它:

g++ -Wall -c object.cpp main.cpp
ar rcs lib.a object.o
g++ -Wall -o main2 main.o lib.a
./main2
> main
  • gObject 的构造函数和析构函数没有被调用...为什么?
  • 如何自动调用它们?

谢谢。

【问题讨论】:

    标签: c++ g++ linker global-variables static-libraries


    【解决方案1】:

    .a 静态库包含多个 .o,但除非您从主应用程序引用它们,否则它们不会链接。
    .o 文件始终为独立链接。

    所以链接器中的.o 文件总是在里面,不管是否被引用,但是从.a 文件中只有引用.o 的对象文件才被链接。

    请注意,静态全局对象在您实际引用编译单元中的任何内容之前不需要初始化,大多数编译器会在 main 之前初始化它们,但唯一的要求是它们在任何函数之前初始化编译单元被执行。

    【讨论】:

    • 谢谢。似乎可以通过使用链接器选项 -Wl,--whole-archive (或 MacOSX 上的 -Wl,-all_load)来强制链接 .a 中包含的所有 .o 文件...
    • 另见 -force_load for MacOSX
    • 如果1.osome.a中的2.o都有两个同名的全局变量会有什么问题吗?它们是否可以链接到一个可执行文件中(考虑以下情况:全局被引用/不被可执行文件引用)?
    • 看来我找到了问题的答案:这两个符号必须进入可执行文件的一个符号表,这会产生冲突。当目标文件形成单独的库时,符号表是分开的。
    猜你喜欢
    • 2013-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多