printf использует sbrk, конфликтуя с пользовательским распределителем памяти - PullRequest
0 голосов
/ 10 февраля 2020

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

Ссылка: Значение sbrk (0) увеличивается после вызова printf В принципе, любая другая функция glib c, использующая 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

1 Ответ

0 голосов
/ 10 февраля 2020

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

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

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

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

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

...