printf использует sbrk, конфликтующий с настраиваемым распределителем памяти

Привет, я написал распределитель памяти и отлично работает. Я использую sbrk / brk для выделения и освобождения страниц. Но все ломается в тот момент, когда я начинаю печатать информацию с помощью printfs. Поиск в Google показывает, что - printf внутренне также использует sbrk. Итак, другая функция glibc (printf) неожиданно использует модифицированный сегмент кучи sbrk - нарушая бухгалтерию, которую выполняет распределитель памяти.

Ссылка: в основном значение sbrk (0) увеличивается после вызова printf, любая другая функция glibc, использующая sbrk, сломает мой распределитель памяти. Можете ли вы предложить возможное решение?

Вставка следа ниже, показывающего, что 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

person Abhishek Sagar    schedule 10.02.2020    source источник
comment
Это невозможно; sbrk() используется внутренним распределителем памяти libc, поэтому многие функции libc используют его неявно. Либо вообще не используйте libc, либо выделите память с помощью malloc() или mmap().   -  person Ctx    schedule 10.02.2020


Ответы (1)


Комментарий Ctx:

Это невозможно; sbrk() используется внутренним распределителем памяти libc, поэтому многие функции libc используют его неявно. Либо вообще не используйте libc, либо выделите память с помощью malloc() или mmap().

верно. Вы можете использовать sbrk, только если не используете malloc, и вы не можете знать, используете ли вы malloc, потому что, если иное не задокументировано реализацией, что-либо в libc может это сделать.

Если ваша библиотека libc поддерживает замену malloc (примечание: большинство из них поддерживают), тогда вы можете написать полную замену malloc (включая все функции семейства malloc, а не только сам malloc), которая либо не использует sbrk, либо сотрудничает с вами. , а затем вы можете использовать его. Однако в противном случае вы просто не можете использовать sbrk.

Также обратите внимание, что в некоторых средах, в том числе часто с исполняемыми файлами, не зависящими от позиции (PIE), sbrk будет иметь мало памяти для работы или вообще не будет иметь с ней работу и часто будет давать сбой только после нескольких выделений или вообще не будет из-за запуска в память, отображаемую для что-то другое. Вся концепция sbrk является обратной, и ее вообще не следует использовать в современном коде. Для некоторых стратегий распределителя это может иметь смысл в качестве одного из вариантов бэкэнда с использованием mmap или чего-то еще. Но это никогда не должно быть единственным способом получения новой памяти вашим распределителем, и, на мой взгляд, поддерживать его вообще бесполезно. mmap лучше почти во всех отношениях.

person R.. GitHub STOP HELPING ICE    schedule 10.02.2020