【问题标题】:Should LD_PRELOAD load module or just use module to replace symbolsLD_PRELOAD 应该加载模块还是只使用模块来替换符号
【发布时间】:2012-08-03 21:20:05
【问题描述】:

我们有一个用 g++ 编译的多线程 c++ 应用程序,在嵌入式 powerpc 上运行。为了在持续集成测试中对此进行内存泄漏测试,我们创建了一个堆分析器,它加载了ld_preload

我们希望保证ld_preloaded 模块中的函数在其他任何事情发生之前被调用(包括创建静态对象等)。更重要的是,我们希望在进程退出之前调用另一个函数,以便堆分析器可以输出其结果。我们看到的问题是,在我们的ld_preloaded 模块中发生任何事情之前,我们的应用程序中的向量是在全局文件范围内创建的。向量在 main 中的大小增加。关闭时,我们预加载模块中的destructor 函数在向量被销毁之前被调用。

我们有什么方法可以编写一个预加载的模块来在其他任何事情之前和之后运行一个函数?我们尝试使用__attribute__((constructor))destructor,但没有成功。

回到问题标题,我开始怀疑ld 在解析符号以供后续模块加载时只查看预加载的模块。它实际上并没有首先加载预加载的模块。任何人都可以为我们阐明这一点吗?

【问题讨论】:

    标签: c++ linux ld-preload


    【解决方案1】:

    最初,您无法控制来自不同翻译单元的构造函数的顺序。因此,这也扩展到了共享库。

    但是,较新版本的GCC 支持将优先级参数应用于constructor 属性,这应该允许您控制您的指定函数何时相对于其他全局构造函数运行。未指定时的默认优先级是最大优先级值。因此,您在下面设置的任何优先级都应该使您的构造函数在它们之前运行,而您的析构函数在它们之后运行。

    static int initialize () __attribute__((constructor(101)));
    static int deinitialize () __attribute__((destructor(101)));
    
    static int initialize () {
        puts("initialized");
    }
    
    static int deinitialize () {
        puts("deinitialized");
    }
    

    101 似乎是允许指定的最低优先级。 65535 是最高的。较小的数字首先执行。

    【讨论】:

    • 不幸的是,这没有任何影响。进一步阅读似乎表明对 C++ 应用程序的真正入口点的追求永无止境。
    • 很抱歉没有成功。那我只能为你建议一个解决方法。如果您改为动态分配堆分析器,它将永远不会被破坏。如果它在内存映射文件中保持其状态,您可以稍后在程序结束时分析该文件。
    • 这是一个好主意,因为它始终保证工作。我们选择修改我们的代码以避免该问题,但我会将其记录为未来的增强功能。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-24
    • 1970-01-01
    • 2017-02-14
    • 2019-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多