在应用程序中替换Linux中Glibc的malloc的四种方法
来源:互联网 发布:淘宝店铺激活实名认证 编辑:程序博客网 时间:2024/05/29 15:12
转自:http://www.xuebuyuan.com/2223733.html
打算优化系统的内存分配,接管
glibc提供的内存管理,但是整个工程的代码量很大,使用
malloc
、
realloc
、
calloc
和
free
的地方到处都是,如果自己写好的接口需要重命名所有的调用,先不说工作量,部分没有权限查看代码的
.a
文件就搞不定了。所以需要替换掉系统的
malloc
,保证原有调用的名称不变。经过尝试,共有四种方法可以替换,各有优缺点吧。
方案
1
使用环境变量
LD_PRELOAD
环境变量
LD_PRELOAD
指定程序运行时优先加载的动态连接库,这个动态链接库中的符号优先级是最高的。标准
C
的各种函数都是存放在
libc.so.6
的文件中,在程序运行时自动链接。使用
LD_PRELOAD
后,自己编写的
malloc
的加载顺序高于
glibc
中的
malloc
,这样就实现了替换。用法:
[littlefang]$
LD_PRELOAD=" ./mymalloc.so"
这是最实用的替换方法,动态链接库加载过程中提供了初始化函数,可以轻易的获得系统
malloc
的句柄,再将它做进一步的管理,
Hoard
(参见
深入
Linux
的内存管理,关于
PTMalloc3
、
Hoard
和
TCMalloc
)的就是这样实现的。
方案
2
malloc
调试变量
__malloc_hook
是一组
glibc
提供的
malloc
调试变量中的一个,这组变量包括:
copy to clipboard
?
- void
*(*__malloc_hook)(
size_t
size,
const
void
*caller); - void
*(*__realloc_hook)(
void
*ptr,
size_t
size,
const
void
*caller); - void
*(*__memalign_hook)(
size_t
alignment,
size_t
size,
const
void
*caller); - void
(*__free_hook)(
void
*ptr,
const
void
*caller); - void
(*__malloc_initialize_hook)(
void
); - void
(*__after_morecore_hook)(
void
);
只要你在程序中写上
”__malloc_hook
= my_malloc_hook;”
,之后的
malloc
调用都会使用
my_malloc_hook
函数,方便易行。但是这组调试变量不是线程安全的,当你想用系统
malloc
的时候不得不把他们改回来,多线程调用就得上锁了。因此方案
2
不很适用于系统内存优化,勉强用来简单管理线程内存使用。
详细用法请猛击这里
方案
3
编译自己的
libmalloc.a
关于重载
glibc
的
malloc
库,
ChinaUnix
上有这样的讨论
:
如果我用
cc -o myprog
myprog.c -lmylib
,
而不想修改缺省的
ld
的命令行参数或者
linker
脚本,不知可不可以?
这个方法确实比较理想,只需要
make
一次就
OK
了,不用更改环境变量,省得担心后台运行的问题。后面有人回复让楼主试试,不知道楼主试了没有,我试了一下。
若要把系统内存管理起来,首先还是要向操作系统申请内存,这个问题对于
LD_PRELOAD
方案很简单,链接库加载时就可以把
glibc
中的
malloc
加载进来,以后直接调用就可以了,如:
real_malloc =
dlsym(RTLD_NEXT, "malloc");
但是你如果使用自己编译的
malloc
库,在你调用
dlsym
这个函数时,
dlsym
会调用
dlerror
,
dlerror
会调用
calloc
,
calloc
要调用
malloc
,而你的
malloc
正在初始化等待
dlsym
返回中,于是死循环了。有人说,在调用没有初始化完毕的
malloc
时,返回
NULL
,我试了
dlsym
不认账,加载可耻的失败了。在满世界的寻找
dlsym
的替代品未果后,我把目光瞄住了
tcmalloc
(参见
深入
Linux
的内存管理,关于
PTMalloc3
、
Hoard
和
TCMalloc
)。
Tcmalloc
使用时需要在链接时加上
-ltcmalloc
即可,它代码里也没使用
dlsym
,大略了看了下它的代码,它使用
mmap
从系统获取的内存。
void *mmap(void
*addr, size_t len, int prot, int flags, int fildes, off_t off);
这种方法从页面级就要对系统内存进行管理,
Glibc
中的
malloc
就是使用
mmap
和
brk
两个函数从程序堆中获得内存的。无疑,这比起用
malloc
分配的内存复杂了很多。
方案
4
链接过程控制
ld
中有一个选项
–wrap
,当查找某个符号时,它优先先解析
__wrap_symbol,
解析不到才去解析
symbol
。例如:
copy to clipboard
?
- void
*__wrap_malloc (
size_t
c) - {
- printf ("malloc called with %zu/n"
, c); - return
__real_malloc (c); - }
当其它文件与你实现
__wrap_malloc
函数的文件链接时使用
--wrap
malloc
,则所有到
malloc
的调用都是会链接到
__wrap_malloc
上。只有调用
__reall_malloc
时才会调用真正的
malloc
。
copy to clipboard
?
- #include <stdio.h>
- #include <stdlib.h>
- void
*__real_malloc(
size_t
); - void
*__wrap_malloc(
size_t
c) - {
- printf("My MALLOC called: %d/n"
, c); - return
__real_malloc(c); - }
- int
main (
int
argc,
char
*argv[]) - {
- void
*ptr = malloc(12); - return
0; - }
编译
[littlefang]$
gcc wrap.c -o wrap -Wl,-wrap,malloc
运行
[littlefang]$
./wrapMy MALLOC
called: 12
Gcc
或
g++
编译使用
–Wl
选项,以指定链接器参数,比如同时替换
malloc,free
,
realloc
就要用
gcc wrap.c -o wrap -Wl,-wrap,malloc
-Wl,-wrap,free
-Wl,-wrap,realloc
。
特别需要注意的是,如果你的
__wrap_malloc是用
C++
实现的,千万不要忘记加上
extern
“C”
做修饰,不然会出现"undefine reference to __wrap_malloc"。
- 在应用程序中替换Linux中Glibc的malloc的四种方法
- 在应用程序中替换Linux中Glibc的malloc的四种方法
- 在应用程序中替换Linux中Glibc的malloc的四种方法 .
- 转:在应用程序中替换Linux中Glibc的malloc的四种方法
- 在应用程序中替换Linux中Glibc的malloc的四种方法
- 在应用程序中替换Linux中Glibc的malloc的四种方法
- 在应用程序中替换Linux中Glibc的malloc的四种方法
- 在应用程序中替换Linux中Glibc的malloc的四种方法
- Glibc 中malloc的实现
- glibc中malloc的详细解释
- glibc中malloc的详细解释
- glibc中malloc的详细解释
- android中完全退出当前应用程序的四种方法
- android中完全退出当前应用程序的四种方法
- android中完全退出当前应用程序的四种方法
- android中完全退出当前应用程序的四种方法
- android中完全退出当前应用程序的四种方法
- 在应用程序中调用控制台的方法
- extjs 组件与布局
- Xmanager Enterprise 4连接不上xshell
- 编程题
- 栈
- Android MVP 使用教程
- 在应用程序中替换Linux中Glibc的malloc的四种方法
- CentOS下 mysql5.6.* 主从配置
- HTTP协议是做什么的
- iOS---Touch ID于密码的简易开发教程
- 页面布局 栅格系统
- Codeforces 300D Painting Square (FFT)
- C/C++琐碎知识归纳之二
- Linux 设备驱动中的 I/O模型(一)—— 阻塞和非阻塞I/O
- python from multiprocessing import Pool,Process,Value,Array,Manager