Можно ли найти память, выделенную указателю, без поиска оператора malloc - PullRequest
14 голосов
/ 28 апреля 2011

Предположим, что я выделил память для некоторого указателя в функции foo:

void foo()
{    
    // ...  
    int *ptr = malloc(20*sizeof(int));  

    bar (ptr);
}  

С foo(), я передаю этот указатель на bar() и, скажем, с bar() на другую функцию.

Теперь, в какой-то момент, я хочу проверить: сколько памяти было выделено для указателя.

Есть ли какой-нибудь возможный путь без поиска оператора:

int *ptr = malloc(20*sizeof(int)); 

, чтобы выяснить, сколько памяти выделено указателю, используя GDB?

Спасибо.

Ответы [ 3 ]

24 голосов
/ 28 апреля 2011

Ответ: это зависит .

Многие системы предоставляют 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

9 голосов
/ 28 апреля 2011

В общем, нет.C не предоставляет способ получить размер выделенного блока памяти.Вам нужно следить за тем, сколько памяти вы выделили самостоятельно.

НО , в некоторых библиотеках C есть функция для получения полезного размера блока памяти - malloc_usable_size (находится в <malloc.h> в системах Linux, без man-страницы).Обратите внимание, что это работает не для всех библиотек libcs ​​и может сообщать о значении, превышающем запрашиваемое вами.Пожалуйста, используйте его только для отладки.

Для полноты моего оригинального ответа, который погружается в низкоуровневые метаданные кучи, перед @Employed Russian, указывающим malloc_usable_size:

НО , вы можете извлечь это вручную.Обратите внимание, однако, что все это может варьироваться в зависимости от вашей ОС, архитектуры процессора и библиотеки C.Я предполагаю, что вы используете eglibc 2.12.1;ваши результаты могут отличаться где-либо еще.

ПРЕДУПРЕЖДЕНИЕ : Серьезно, НЕ используйте это, кроме как для отладки в GDB.В самом деле.Я имею в виду.

Распределитель памяти glibc хранит такие фрагменты памяти (из комментария к документу в 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 (для больших malloc).Все это не так важно;важно то, что размер живет на один шаг размера указателя перед вашей памятью;вам просто нужно замаскировать эти флаги и вычесть размер заголовка:

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

Предупреждение: фактически выделенный размер может быть больше, чем вы запрашивали.Не пытайтесь стать умным и использовать лишнее.Спросите, сколько вам нужно в начале.

Предостережение 2: Это работает только с glibc.И это работает только с определенными версиями glibc.и, следовательно, может сломаться в любой момент без предупреждения.Я не могу подчеркнуть это достаточно; НЕ используйте это в вашем реальном коде;только для отладки, когда вы исчерпали все остальные опции.Ваш код должен самостоятельно отслеживать размеры буфера.

3 голосов
/ 28 апреля 2011

Нет . Вы должны хранить эту информацию самостоятельно, когда вы malloc().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...