printf 使用 sbrk,与自定义内存分配器冲突
printf uses sbrk, conflicting with custom memory allocator
您好,我已经编写了一个内存分配器,并且运行良好。我使用 sbrk/brk 进行页面分配和释放。
但是当我开始使用 printfs 打印信息时,一切都崩溃了。谷歌搜索显示 - printf 在内部也使用 sbrk。因此,另一个 glibc 函数 (printf) 意外地使用了 sbrk 修改的堆段 - 破坏了内存分配器正在进行的簿记。
参考:sbrk(0) value getting increased after calling printf
基本上,任何其他使用 sbrk 的 glibc 函数都会破坏我的内存分配器。
您能否提出可能的解决方案?
粘贴下面显示 printf 最终调用 sbrk 的回溯。即使在打印完成后,我看到,中断指针永远不会恢复到原来的位置。 printf 不应该在它最初位于堆段中的位置恢复中断指针吗?在这方面 printf 的任何替代方案?
(gdb) bt
0 __GI___sbrk (increment=135168) at sbrk.c:40
1 0x00007ffff7e68a99 in __GI___default_morecore (increment=<optimized out>) at morecore.c:47
2 0x00007ffff7e64297 in sysmalloc (nb=nb@entry=592, av=av@entry=0x7ffff7fb2c40 <main_arena>) at malloc.c:2480
3 0x00007ffff7e657b3 in _int_malloc (av=av@entry=0x7ffff7fb2c40 <main_arena>, bytes=bytes@entry=576) at malloc.c:4149
4 0x00007ffff7e65f25 in tcache_init () at malloc.c:2995
5 0x00007ffff7e66ba6 in tcache_init () at malloc.c:3050
6 __GI___libc_malloc (bytes=1024) at malloc.c:3050
7 0x00007ffff7e4f85c in __GI__IO_file_doallocate (fp=0x7ffff7fb3760 <_IO_2_1_stdout_>) at filedoalloc.c:101
8 0x00007ffff7e5f0b2 in __GI__IO_doallocbuf (fp=fp@entry=0x7ffff7fb3760 <_IO_2_1_stdout_>) at libioP.h:904
9 0x00007ffff7e5e198 in _IO_new_file_overflow (f=0x7ffff7fb3760 <_IO_2_1_stdout_>, ch=-1) at fileops.c:752
10 0x00007ffff7e5cbd5 in _IO_new_file_xsputn (n=13, data=<optimized out>, f=0x7ffff7fb3760 <_IO_2_1_stdout_>) at libioP.h:904
11 _IO_new_file_xsputn (f=0x7ffff7fb3760 <_IO_2_1_stdout_>, data=<optimized out>, n=13) at fileops.c:1204
12 0x00007ffff7e44e10 in __vfprintf_internal (s=0x7ffff7fb3760 <_IO_2_1_stdout_>, format=0x555555557334 "\nPage Size = %zu Bytes\n", ap=ap@entry=0x7fffffffdcc0,
mode_flags=mode_flags@entry=0) at ../libio/libioP.h:904
13 0x00007ffff7e308d8 in __printf (format=<optimized out>) at printf.c:33
14 0x000055555555677d in mm_print_memory_usage () at mm.c:613
15 0x00005555555552a9 in main (argc=1, argv=0x7fffffffdf18) at testapp.c:64
Ctx的评论:
This is not possible; sbrk()
is used by the libc memory allocator internally, so many libc functions use it implicitly. Either do not use libc at all, or do your memory allocations with malloc()
or mmap()
.
是正确的。如果不使用 malloc
,则只能使用 sbrk
,并且不知道是否使用 malloc
,因为除非实现另有说明,否则 libc 中的任何内容都可能这样做。
如果你的 libc 支持替换 malloc
(注意:大部分支持)那么你可以写一个完整的 malloc
替换(这包括所有 malloc
系列函数,而不仅仅是 malloc
本身)要么不使用sbrk
,要么配合你使用它,然后你就可以自由使用它了。但是否则,您根本无法使用 sbrk
.
另请注意,在某些环境中,包括经常与位置无关的可执行文件 (PIE),sbrk
将只有很少或没有内存可供使用,并且在仅几次分配后或 none 完全没有,因为 运行 到内存映射为其他东西。 sbrk
的整个概念是倒退的,根本不应该在现代代码中使用。对于一些分配器策略,它作为后端的一种选择可能是有意义的,同时使用 mmap
或其他东西。但它永远不应该是你的分配器获得新内存的唯一方式,而且在我看来,支持它根本没有用。 mmap
几乎在所有方面都更好。
您好,我已经编写了一个内存分配器,并且运行良好。我使用 sbrk/brk 进行页面分配和释放。 但是当我开始使用 printfs 打印信息时,一切都崩溃了。谷歌搜索显示 - printf 在内部也使用 sbrk。因此,另一个 glibc 函数 (printf) 意外地使用了 sbrk 修改的堆段 - 破坏了内存分配器正在进行的簿记。
参考:sbrk(0) value getting increased after calling printf 基本上,任何其他使用 sbrk 的 glibc 函数都会破坏我的内存分配器。 您能否提出可能的解决方案?
粘贴下面显示 printf 最终调用 sbrk 的回溯。即使在打印完成后,我看到,中断指针永远不会恢复到原来的位置。 printf 不应该在它最初位于堆段中的位置恢复中断指针吗?在这方面 printf 的任何替代方案?
(gdb) bt
0 __GI___sbrk (increment=135168) at sbrk.c:40
1 0x00007ffff7e68a99 in __GI___default_morecore (increment=<optimized out>) at morecore.c:47
2 0x00007ffff7e64297 in sysmalloc (nb=nb@entry=592, av=av@entry=0x7ffff7fb2c40 <main_arena>) at malloc.c:2480
3 0x00007ffff7e657b3 in _int_malloc (av=av@entry=0x7ffff7fb2c40 <main_arena>, bytes=bytes@entry=576) at malloc.c:4149
4 0x00007ffff7e65f25 in tcache_init () at malloc.c:2995
5 0x00007ffff7e66ba6 in tcache_init () at malloc.c:3050
6 __GI___libc_malloc (bytes=1024) at malloc.c:3050
7 0x00007ffff7e4f85c in __GI__IO_file_doallocate (fp=0x7ffff7fb3760 <_IO_2_1_stdout_>) at filedoalloc.c:101
8 0x00007ffff7e5f0b2 in __GI__IO_doallocbuf (fp=fp@entry=0x7ffff7fb3760 <_IO_2_1_stdout_>) at libioP.h:904
9 0x00007ffff7e5e198 in _IO_new_file_overflow (f=0x7ffff7fb3760 <_IO_2_1_stdout_>, ch=-1) at fileops.c:752
10 0x00007ffff7e5cbd5 in _IO_new_file_xsputn (n=13, data=<optimized out>, f=0x7ffff7fb3760 <_IO_2_1_stdout_>) at libioP.h:904
11 _IO_new_file_xsputn (f=0x7ffff7fb3760 <_IO_2_1_stdout_>, data=<optimized out>, n=13) at fileops.c:1204
12 0x00007ffff7e44e10 in __vfprintf_internal (s=0x7ffff7fb3760 <_IO_2_1_stdout_>, format=0x555555557334 "\nPage Size = %zu Bytes\n", ap=ap@entry=0x7fffffffdcc0,
mode_flags=mode_flags@entry=0) at ../libio/libioP.h:904
13 0x00007ffff7e308d8 in __printf (format=<optimized out>) at printf.c:33
14 0x000055555555677d in mm_print_memory_usage () at mm.c:613
15 0x00005555555552a9 in main (argc=1, argv=0x7fffffffdf18) at testapp.c:64
Ctx的评论:
This is not possible;
sbrk()
is used by the libc memory allocator internally, so many libc functions use it implicitly. Either do not use libc at all, or do your memory allocations withmalloc()
ormmap()
.
是正确的。如果不使用 malloc
,则只能使用 sbrk
,并且不知道是否使用 malloc
,因为除非实现另有说明,否则 libc 中的任何内容都可能这样做。
如果你的 libc 支持替换 malloc
(注意:大部分支持)那么你可以写一个完整的 malloc
替换(这包括所有 malloc
系列函数,而不仅仅是 malloc
本身)要么不使用sbrk
,要么配合你使用它,然后你就可以自由使用它了。但是否则,您根本无法使用 sbrk
.
另请注意,在某些环境中,包括经常与位置无关的可执行文件 (PIE),sbrk
将只有很少或没有内存可供使用,并且在仅几次分配后或 none 完全没有,因为 运行 到内存映射为其他东西。 sbrk
的整个概念是倒退的,根本不应该在现代代码中使用。对于一些分配器策略,它作为后端的一种选择可能是有意义的,同时使用 mmap
或其他东西。但它永远不应该是你的分配器获得新内存的唯一方式,而且在我看来,支持它根本没有用。 mmap
几乎在所有方面都更好。