覆盖C中的_init函数,它有多安全?

时间:2011-03-29 15:26:29

标签: c linux

我正在以共享库的形式构建调试内存工具,我在运行时链接可执行文件(包括malloc系列的重写方法)。为了处理我的数据结构的初始化,我简单地使用了一个条件变量。每次调用malloc时,我都会检查变量是否未设置,然后调用一个负责初始化结构的函数。现在,这适用于运行单个执行线程的程序,但如果程序包含多个线程,则会出现问题。

确保在用户生成任何线程之前进行初始化的唯一方法(我能想到)是覆盖_init,如图所示in this link

现在这个小例子运行正确,但是当我尝试在我自己的共享库中覆盖_init时,我在尝试链接它时遇到此错误:

memory2.o: In function `_init':
memory2.c(.text+0x0): multiple definition of `_init'
/usr/lib/gcc/i686-linux-gnu/4.4.5/../../../../lib/crti.o(.init+0x0): 
 first defined here
collect2: ld returned 1 exit status

我使用与链接中的示例完全相同的步骤,只是我的共享库还包括一组全局变量和malloc / free等的覆盖版本。

任何人都可以给我指出出错的地方?此外,在覆盖_init时还有什么需要考虑的因素(我猜这不是很正常的事情)。

谢谢

3 个答案:

答案 0 :(得分:9)

请查看以下常见问题解答页面:

http://www.faqs.org/docs/Linux-HOWTO/Program-Library-HOWTO.html#INIT-AND-CLEANUP

它将_init/_fini描述为危险且过时,并建议改为使用__attribute__ ((constructor))__attribute__ ((destructor))

来自gcc manual

  

constructor (priority)   destructor (priority)

     

在   构造函数属性导致   要自动调用的函数   在执行进入main()之前。   同样,析构函数属性   导致调用该函数   main()之后自动生成   已完成或exit()已被调用。   具有这些属性的函数是   用于初始化将要的数据   在...期间隐式使用   执行程序。你可以   提供可选的整数优先级   控制其中的顺序   构造函数和析构函数   跑了。一个较小的构造函数   优先号在a之前运行   具有更高优先级的构造函数   数;相反的关系   适用于析构函数。所以,如果你有   一个分配一个的构造函数   资源和析构函数   两者都释放相同的资源   功能通常具有相同的功能   优先。优先事项   构造函数和析构函数   与指定的相同   namespace-scope C ++对象(参见C ++   属性)。

     

目前不是这些属性   为Objective-C实现。

答案 1 :(得分:1)

1)您可以编写自己的_init或main:

GNU GCC允许您定义自己的与现有符号同名的功能。链接时,您提供-Xlinker --wrap=<symName>的参数。假装你这样做是为了主,你可以通过__real_main(...)

来调用真正的主要内容
int main(int argc, void *argv)
{
    // any code you want here
    return __real_main(argc,argv);
}

2)您可以编写自己的动态链接器。如果这样做,则将.interp部分设置为指向包含动态链接器/加载器的共享对象。

答案 2 :(得分:0)

要克服该错误,请将代码编译为gcc -nostartfiles memory2.c -o memory2,这里我们将跳过构造函数和析构函数。

但不建议覆盖这些。