我正在以共享库的形式构建调试内存工具,我在运行时链接可执行文件(包括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时还有什么需要考虑的因素(我猜这不是很正常的事情)。
谢谢
答案 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
,这里我们将跳过构造函数和析构函数。
但不建议覆盖这些。