LD_PRELOAD无法按预期工作 [英] LD_PRELOAD does not work as expected

查看:123
本文介绍了LD_PRELOAD无法按预期工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下可在任何程序执行之前预加载的库:

Consider the following library which can be preloaded before any program execution:

// 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;

问题在于,尽管始终调用全局变量goodbye的构造函数,但对于某些程序(例如ls:

The problem is that, while the constructor of the global variable goodbye is always called, the destructor is not called for some programs, like ls:

$ LD_PRELOAD=./preload.so ls
Hello

对于其他一些程序,析构函数将按预期方式调用:

For some other programs, the destructor is called as expected:

$ LD_PRELOAD=./preload.so man
Hello
What manual page do you want?
Goodbye!

您能解释一下为什么在第一种情况下不调用析构函数吗? 上面的问题已得到解答,即程序可能会使用_exit(),abort()退出.

Can you explain why the destructor is not called in the first case? the above question has been already answered, that is a program might well use _exit(), abort() to exit.

但是:

有没有办法在预加载的程序退出时强制调用给定功能?

推荐答案

lsatexit (close_stdout);作为其初始化代码.完成后,它将关闭标准输出(即close(1)),因此您的coutprintfwrite(1, ...操作将不会打印任何内容.这并不意味着不调用析构函数.您可以通过例如在析构函数中创建一个新文件.

ls has atexit (close_stdout); as its initialisation code. When it finishes, it closes stdout (i.e. close(1)), so your cout, printf or write(1, ... operations will not print anything. It doesn't mean destructor isn't called. You can verify this by e.g. creating a new file in your destructor.

http://git.savannah. gnu.org/cgit/coreutils.git/tree/src/ls.c#n1285 这是GNU coreutils ls中的这一行.

http://git.savannah.gnu.org/cgit/coreutils.git/tree/src/ls.c#n1285 here is the line in GNU coreutils ls.

不仅仅是ls,大多数coreutils都这样做.不幸的是,我不知道他们为什么宁愿为什么关闭它的确切原因.

It is not just ls, most of coreutils do that. Unfortunately, I don't know exact reason why they prefer to close it.

关于如何找到(或至少我所做的)的旁注-下次或使用无源代码访问的程序时可能会有所帮助:

Side note on how this could be found (or at least what I did) - may help next time or with program with no source code access:

析构函数消息是用/bin/true(我想到的最简单的程序)打印的,而不是用lsdf打印的.我从strace /bin/truestrace /bin/ls开始,比较了最新的系统调用.对于ls,它显示close(1)close(2),对于true,则没有显示.之后事情开始变得有意义,我只需要验证是否调用了析构函数即可.

Destructor message is printed with /bin/true (simplest program I could think of), but isn't printed with ls or df. I started with strace /bin/true and strace /bin/ls and compared latest system calls. It shown close(1) and close(2) for ls, but none for true. After that things started to make sense and I just had to verify that destructor is called.

这篇关于LD_PRELOAD无法按预期工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆