Можно ли найти память, выделенную указателем, без поиска оператора malloc
Предположим, что я выделил память для некоторого указателя в функции foo
:
void foo()
{
// ...
int *ptr = malloc(20*sizeof(int));
bar (ptr);
}
От foo()
, я передаю этот указатель на bar()
и скажу от bar()
к другой функции.
Теперь, в некоторый момент времени, я хочу проверить: сколько памяти было выделено указателю.
Есть ли какой-либо возможный способ, не ища выражения:
int *ptr = malloc(20*sizeof(int));
чтобы выяснить, сколько памяти выделено указателю, используя GDB?
Спасибо.
Ответы
Ответ 1
Ответ: это зависит.
Многие системы обеспечивают msize()
[1], malloc_usable_size()
[2] или аналогичную функцию. Если вы находитесь в такой системе, (gdb) print malloc_usable_size(ptr)
- это все, что вам нужно.
[1] http://msdn.microsoft.com/en-us/library/z2s077bc(v=vs.80).aspx
[2] http://www.slac.stanford.edu/comp/unix/package/rtems/doc/html/libc/libc.info.malloc.html
Ответ 2
В общем, нет. C не предоставляет способ получить размер выделенного блока памяти. Вам нужно следить за тем, сколько памяти вы выделили себе.
НО, в некоторых библиотеках C есть функция для получения полезного размера блока памяти - malloc_usable_size (найдено в <malloc.h>
в системах Linux без man-страницы). Обратите внимание, что это не работает на всех libcs и может сообщить значение больше, чем вы запросили. Пожалуйста, используйте его только для отладки.
Для полноты моего первоначального ответа, который погружается в метаданные низкоуровневого кучи, до @Employed Russian, указывающего malloc_usable_size
:
НО, вы можете извлечь это вручную. Обратите внимание, однако, что все это может варьироваться в зависимости от вашей ОС, архитектуры процессора и библиотеки C. Предполагаю, что вы используете eglibc 2.12.1; ваши результаты могут отличаться в другом месте.
ПРЕДУПРЕЖДЕНИЕ: серьезно, НЕ используйте это, кроме как для отладки в gdb. В самом деле. Я имею в виду.
Распределитель памяти glibc хранит такие фрагменты памяти (из комментария doc в malloc/malloc.c):
chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of previous chunk, if allocated | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of chunk, in bytes |M|P|
mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| User data starts here... .
. .
. (malloc_usable_size() bytes) .
. |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of chunk |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Ваши данные здесь находятся в "mem", а размер чанка включает заголовок. Флаг P указывает, действительны ли данные предыдущего блока, а M указывает, что это отображение mmap (для больших mallocs). Все это не слишком важно; важно то, что размер живет с одним размером указателя до вашей памяти; вам просто нужно замаскировать эти флаги и вычесть размер заголовка:
Breakpoint 1, main () at test.c:8
8 char *a = malloc(32);
(gdb) n
10 free(a);
(gdb) print (*((unsigned long long*)a - 1) & ~3) - sizeof(unsigned long long)*2
$14 = 32
Предостережение. Фактически выделенный размер может быть больше, чем вы запросили. Не пытайтесь умудряться и использовать избыток. Спросите, сколько вам нужно в начале.
Caveat 2: Это работает только с glibc. И он работает только с определенными версиями glibc. и, таким образом, может прерываться в любой момент без предупреждения. Я не могу это подчеркнуть; НЕ используйте это в своем действительном коде; только для отладки, когда вы исчерпали все остальные варианты. Ваш код должен самостоятельно отслеживать размеры своих буферов.
Ответ 3
Нет. Вы должны хранить эту информацию самостоятельно, когда вы malloc()
.