Mar*_*tin 25 c++ linux gcc ld ld-preload
考虑以下库,可以在任何程序执行之前预先加载:
// g++ -std=c++11 -shared -fPIC preload.cpp -o preload.so
// LD_PRELOAD=./preload.so <command>
#include <iostream>
struct Goodbye {
Goodbye() {std::cout << "Hello\n";}
~Goodbye() {std::cout << "Goodbye!\n";}
} goodbye;
Run Code Online (Sandbox Code Playgroud)
问题是,虽然goodbye总是调用全局变量的构造函数,但是没有为某些程序调用析构函数,例如ls:
$ LD_PRELOAD=./preload.so ls
Hello
Run Code Online (Sandbox Code Playgroud)
对于其他一些程序,析构函数按预期调用:
$ LD_PRELOAD=./preload.so man
Hello
What manual page do you want?
Goodbye!
Run Code Online (Sandbox Code Playgroud)
你能解释为什么在第一种情况下没有调用析构函数吗?编辑:上面的问题已经得到解答,那就是程序可能会使用_exit(),abort()来退出.
然而:
有没有办法在预加载的程序退出时强制调用给定的函数?
kel*_*tar 31
ls有atexit (close_stdout);初始化代码.当它完成,它关闭标准输出(即close(1)),所以你的cout,printf或者write(1, ...操作不会显示任何信息.它并不意味着不会调用析构函数.您可以通过在析构函数中创建新文件来验证这一点.
http://git.savannah.gnu.org/cgit/coreutils.git/tree/src/ls.c#n1285这里是GNU coreutils ls中的一行.
它不仅仅是ls,大多数coreutils都这样做.不幸的是,我不知道他们为什么喜欢关闭它的确切原因.
关于如何找到它(或者至少我做了什么)的附注 - 可能有助于下次或没有源代码访问的程序:
析构函数消息打印/bin/true(我能想到的最简单的程序),但不打印ls或df.我开始使用strace /bin/true并strace /bin/ls比较最新的系统调用.它显示close(1)和close(2)为ls,但没有true.之后事情开始变得有意义,我只需要验证析构函数是否被调用.
如果程序通过_exit(POSIX)或_Exit(C99)退出或程序异常终止(abort致命信号等),则无法调用析构函数.我没有看到任何解决方法.
| 归档时间: |
|
| 查看次数: |
2336 次 |
| 最近记录: |