用静态链接重新定义malloc/free有多个定义错误
Redefine malloc/free with static linking has multiple definition error
最近,我的公司想把编译器从gcc-3.4更新到gcc-4.5。但是,我们客户的机器可能没有最新的libstdc++.so
,所以我们想静态链接我们的二进制文件。
我们的程序需要定制malloc()/free()
以满足非常高的性能要求。
我修改了makefile,在链接时添加了-static
,并得到了以下错误信息:
/usr/lib64/libc.a(malloc.o)(.text+0x18c0): In function `free':
: multiple definition of `free'
../../ic/src/memmgr/libmemmgr_mt_thread.a(memmgr_mt_thread.o)(.text+0x3430): first defined here
/usr/bin/ld: Warning: size of symbol `free' changed from 271 in ../../ic/src/memmgr/libmemmgr_mt_thread.a(memmgr_mt_thread.o) to 255 in /usr/lib64/libc.a(malloc.o)
/usr/lib64/libc.a(malloc.o)(.text+0x3970): In function `malloc':
: multiple definition of `malloc'
../../ic/src/memmgr/libmemmgr_mt_thread.a(memmgr_mt_thread.o)(.text+0x29c0): first defined here
/usr/bin/ld: Warning: size of symbol `malloc' changed from 281 in ../../ic/src/memmgr/libmemmgr_mt_thread.a(memmgr_mt_thread.o) to 461 in /usr/lib64/libc.a(malloc.o)
/usr/lib64/libc.a(malloc.o)(.text+0x4050): In function `realloc':
: multiple definition of `realloc'
../../ic/src/memmgr/libmemmgr_mt_thread.a(memmgr_mt_thread.o)(.text+0x3e80): first defined here
/usr/bin/ld: Warning: size of symbol `realloc' changed from 335 in ../../ic/src/memmgr/libmemmgr_mt_thread.a(memmgr_mt_thread.o) to 927 in /usr/lib64/libc.a(malloc.o)
好的,这是合理的,因为libc.a
已经有malloc()/free()
了。
但是让我困惑的是为什么在动态链接时没有错误。我搜索了一下,发现了这个问题:如何在Linux中重新定义malloc()以便在c++中使用。答案是链接器对库文件(a)和目标文件(.o)的处理方式不同。现在我知道为什么静态链接会出错,而动态链接不会。
然而,我尝试了答案中描述的解决方案,直接用目标文件替换了库文件,但没有区别。我仍然得到了多个定义链接错误。我也尝试了-static-libgcc
(因为我不知道该怎么做,我只是尝试了我在gcc
手册页中看到的一切),但它也没有帮助。
我不必使用静态链接。我只是想解决libstdc++.so
版本的问题。如有任何建议,我将不胜感激。
提前感谢。
对不起,我没有说清楚。使用#define malloc ...
在这里可能没有帮助。因为我们的程序是c++。#define
习语只能影响malloc()/free()
函数。但是我们的程序实际上使用new/delete
来分配/释放内存。D
如果您主要关心的是libstdc++的可用性。因此,在目标系统中,为什么不简单地将新版本与应用程序一起发布呢?
我认为静态链接在任何情况下都不是一个好的解决方案,编译项目变得更加困难,如果你自己使用共享对象(例如使用你自己的插件时),那么静态链接就会停止工作,因为静态库的单独副本需要链接到每个二进制文件,可执行文件等等。你能想象如果在同一个程序中有多个全局变量的实例,锁等当它被加载时会发生什么吗?我告诉你:崩溃。所以不要静态链接,复制libstdc++。所以到一个私有目录(我不知道你的应用程序安装在哪里,但如果它有一个私有前缀,那很简单,使用$prefix/lib)。
然后设置LD_LIBRARY_PATH,或者使用-rpath将路径编码为二进制,以便链接器找到它。当然,这意味着你链接的所有库,也可能使用libstdc++,也应该和你的应用一起发布。
但是大小方面,它是相同的,对于静态链接,您也将携带该代码。
可以通过rpath使用动态链接。见"man ld"answers"man ld.so"
$ORIGIN扩展可能是有用的:将你需要的每一个。so包在与程序(或子目录)相同的目录中,并在与ld链接时使用"-rpath $ORIGIN"或"-rpath,'$ORIGIN/lib"。
许多程序使用这种方法来捆绑它们自己的私有库。
另一种方法是使用.sh脚本设置LD_LIBRARY_PATH,然后调用真正的程序(下载firefox二进制文件并查看run-mozilla.sh)。然而,LD_LIBRARY_PATH将泄漏给子进程。所以它不是那么干净,但可能更适合非GNU系统。
您应该在项目中使用自己的free/alloc/realloc函数,但我强烈建议您使用与标准库相同的名称。
例如void* myProject_malloc(...)
void myProject_free()
你可以将它与宏结合起来,将分配函数重定向到你的函数,但我不建议你这样做。你必须检查你所有的源代码是否包括这个头文件,编译器可以提醒你宏重定义(取决于编译器和你正在使用的选项)
#define malloc(x) myProject_malloc(x)
#define free() myProject_free()
如果你不想使用标准库,你应该使用gcc选项:"- nosdlib "。但是如果这样做,就不能使用标准库的任何其他函数。
如果使用GNU libc,可以使用GNU malloc Hooks。我对这个API的设计不太满意,所以我不建议使用它。
您可以尝试修补libc。删除malloc/
中的所有代码,并将其替换为您的实现。
使用相同的想法,您可以尝试使用libc.a
,删除包含malloc
和朋友的所有.o
文件(这应该是与malloc/*.c
对应的大部分.o
文件)并重新打包libc.a
与您的实现。
很可能需要更改自定义分配例程的名称。之后,您应该使用答案中描述的方法来节省时间,这样您就不必将所有调用更改为新名称:
#define malloc myMalloc
#define free myFree
如果你只需要为c++做,你可以覆盖new, delete, new[], delete[]操作符。参见18.6.1 "存储分配和释放"
void* operator new(std::size_t size);
[...]
void operator delete(void* ptr);
"可替换的:c++程序可以定义一个带有此函数签名的函数,以取代c++标准库定义的默认版本。"
我不知道它是否与静态链接工作然而(不知道它是如何实现的)。
- 在提升multi_index容器中,是否定义了"default index"?
- #定义c-预处理器常量..我做错了什么
- 用C++中的一个变量定义一个常量
- 部分定义/别名模板模板参数
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- #为""定义宏;静态";针对不同的上下文
- 如何确保C++函数在定义之前声明(如override关键字)
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- 当类在C++中定义时,有什么方法可以"register"类吗?
- 在命名空间中定义函数还是限定函数
- 此代码是否违反一个定义规则
- 编译C++时未定义的引用
- 不同翻译单元中不可重载的非内联函数定义
- 为什么在定义函数之前先声明它
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- emplace_back和push_back给出错误'double free or corruption (fasttop)'尽管定义了复制和移动构造函数
- C++ AWSCredentials:对"Aws::Free(void*)"的未定义引用
- QT5:未定义的对"QString::free(QString::D ata*)"的引用
- "lock-free"的含义是否由C++标准定义?
- 用静态链接重新定义malloc/free有多个定义错误