【问题标题】:Static lib loading related issue静态库加载相关问题
【发布时间】:2010-10-07 09:36:45
【问题描述】:

假设我想对生成的二进制文件中的库进行版本控制。对于静态库,我认为这种方法可行,但它不起作用:

LibInfo.h - 所有 libinfo 类的基类。构造子对象时,在gvLibInfo 向量中注册一个对象。

#ifndef IFACE_H
#define IFACE_H

#include <vector>

class LibInfo;
extern std::vector<LibInfo*> gvLibInfo;

class LibInfo
{
    public:
        virtual int getversion() = 0;
        void reglib()
        {
            gvLibInfo.push_back(this);
        }

        LibInfo()
        {
            reglib();
        }
        virtual ~LibInfo()
        {}
};


#endif

Lib1.h - 从 LibInfo 派生并创建一个对象 l1。除了 getversion 返回 2 之外,Lib2.h 是相同的。

#ifndef LIB1_H
#define LIB1_H

#include "LibInfo.h"

class Lib1 : public LibInfo
{
    public:
        int getversion()
        {
            return 1;
        }

    private:
};

Lib1 l1;

#endif

main.cpp

#include "Lib1.h"
#include <iostream>
using namespace std;

vector<LibInfo*> gvLibInfo;

int main()
{       
    for(vector<LibInfo*>::iterator it = gvLibInfo.begin(); it != gvLibInfo.end(); it++)
    {       
        cout << (*it)->getversion() << endl;
    }

    return 0;
}

编译 -

g++ -c Lib1.h -o Lib1.o
g++ -c Lib2.h -o Lib2.o
ar cr lib.a Lib1.o Lib2.o
g++ main.cpp -o app -L/home/duminda/statictest/lib.a

当我跑步时,什么也没有发生。我认为这可能是由于以下几个原因之一:

  1. 在生成Lib1 l1 时,尚未构造gvLibInfo
  2. 我在某处看到链接器将从静态库中删除所有未使用的变量。但是,当我在二进制文件 nm 上运行时,它会显示:

0000000000603280 B gvLibInfo

0000000000603270 B l1

0000000000603278 B l2

我猜l1 & l2(Lib2 类的对应对象存在,但那个“B”标志是什么意思? 3. 其他我不知道的事情。

【问题讨论】:

  • 我运行了一个 gdb 会话。确实似乎在加载静态库后构造了向量。那么,1.我可以以某种方式延迟 lib 加载或强制向量的构建吗? 2. 或者,我只需要使用原始数据类型?
  • 此外,如果我从 main.cpp 中删除 #include "Lib1.h" 并将其替换为 #include "LibInfo.h" 那么我 nm 不会显示符号 l1l2
  • :D。我的第一个问题解决了。 __attribute__((init_priority())) 解决了这个问题。现在我希望有人帮助我解决上述问题。 :)
  • 这是您应该使用 --whole-archive 更新的问题。
  • 但是,如果我这样做了,没人会注意到吗?

标签: c++ linux linker g++ static-libraries


【解决方案1】:

将 main.cpp 的顶部更改为如下所示,以便在派生实例之前创建向量。

#include "LibInfo.h"

std::vector<LibInfo*> gvLibInfo;

#include "Lib1.h"
#include "Lib2.h"

顺便说一句,nm 中的“B”表示 BSS 中的符号(未初始化的数据)。 nm 的手册页列出了所有符号类型。

【讨论】:

    【解决方案2】:

    question 的第一个答案建议使用 --whole-archive 标志。 主要区别在于,库不是引用外部对象,而是引用 到外部函数。

    使用 -L 不会进行链接,而是使用 -l,即它应该是:

    -L/path/to/libdir -lname
    

    如果您的图书馆是:

    /path/to/libdir/libname.a
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多