c++ - 静态对象的析构函数不(总是)用 LD_PRELOAD 调用
问题描述
我想使用 LD_PRELOAD 机制 GNU 的动态加载器将代码注入其他二进制文件。在我的代码中,我使用静态对象在增强程序(稍后称为 Prog)的开始和结束时执行代码。我不应该关心静态初始化程序的执行顺序,因为我不访问 Prog 的任何数据,我也不关心我的代码何时运行,只要它“足够接近”Prog 的“main”的开始/结束。
问题在于,对于某些二进制文件,这种方法可以正常工作,而对于其他二进制文件,则根本不调用静态对象的析构函数。
#include <iostream>
namespace {
struct Stat {
Stat() { std::cerr << "Ctor" << std::endl; }
~Stat() { std::cerr << "Dtor" << std::endl; }
};
}
Stat s;
汇编:
$ g++ -shared -fpic -o ~/preload.so preload.cc
用法:
$ LD_PRELOAD=~/preload.so /bin/true
Ctor
Dtor
$ LD_PRELOAD=~/preload.so /bin/sleep 1
Ctor
在第一种情况下,true
一切都按预期工作,但在第二种情况下(以及大多数/所有其他情况),析构函数永远不会被调用。我排除了标准流“过早”破坏的问题,方法是将字符串输出替换为sleep
…适用于true
,失败为sleep
。(编辑:忽略最后一部分。我搞砸了编译并sleep
再次运行版本。sleep
实际上有效,所以@dms是正确的。它没有解释gdb中双重打印的“Ctor”,但我不在乎关于那个神器的东西太多了。)
更奇怪的是。当我尝试在 gdb 中运行示例时(使用set env LD_PRELOAD ...
),“Ctor”被打印两次。如果我在它处设置断点,Stat
则仅在第一次输出“Ctor”后触发。断点~Stat
确实触发但仍然没有输出。
有一个关于 DLL 中的静态对象 dtors的类似问题。那里的答案要么是特定于 Windows 的,要么暗示永远不会为动态加载的库调用静态 dtor,这在我的情况下显然不是真的。
解决方案
推荐阅读
- symfony - 修改引导数据表
- javascript - 为什么 headerTransparent 和自定义参数 headerTitle 不能一起工作?
- salesforce - 在 LWC 中重新加载导航选项卡
- wpf - 适合 WPF Mvvm 中的窗口
- postgresql - 尝试在一个连接到另一个 postgres 的容器中运行 go 程序时出现拨号错误(拨号 tcp 172.18.0.2:8001:连接:连接被拒绝)
- elasticsearch - 从 Elasticsearch 中删除数据 Maxed out index
- azure-cosmosdb - 从 Cosmos DB 一次查询中选择相关文档
- javascript - 有没有办法使用 JavaScript 在其默认应用程序中打开文件?
- sql-server - 如何使用默认字符串添加列
- python - Pandas:加入/合并/连接两个数据框