Как я могу получить размер массива из указателя в C? - PullRequest
66 голосов
/ 24 октября 2008

Я выделил «массив» размером mystruct n, например:

if (NULL == (p = calloc(sizeof(struct mystruct) * n,1))) {
 /* handle error */
}

Позже я имею доступ только к p и больше не имею n. Есть ли способ определить длину массива только по указателю p?

Я полагаю, что должно быть возможным, поскольку free(p) делает именно это. Я знаю, malloc() следит за тем, сколько памяти он выделил, и поэтому он знает длину; возможно есть способ запросить эту информацию? Что-то вроде ...

int length = askMallocLibraryHowMuchMemoryWasAlloced(p) / sizeof(mystruct)

Я знаю, что должен просто переработать код, чтобы я знал n, но я бы предпочел, чтобы это было невозможно. Есть идеи?

Ответы [ 13 ]

1 голос
/ 24 октября 2008

Одна из причин того, что вы не можете спросить библиотеку malloc о размере блока, заключается в том, что распределитель обычно округляет размер вашего запроса, чтобы удовлетворить некоторому требованию минимальной гранулярности (например, 16 байт). Поэтому, если вы попросите 5 байтов, вы получите блок размером 16 обратно. Если бы вы взяли 16 и поделили на 5, вы бы получили три элемента, когда вы действительно выделяете только один. Библиотеке malloc потребовалось бы дополнительное пространство для отслеживания того, сколько байтов вы запросили в первую очередь, поэтому лучше всего вы сами это отследите.

1 голос
/ 24 октября 2008

Я не знаю, как это сделать, но я бы подумал, что это будет связано с осмотром внутренних частей malloc, что, как правило, очень, очень плохая идея.

Почему вы не можете сохранить размер выделенной памяти?

РЕДАКТИРОВАТЬ: Если вы знаете, что вы должны переработать код, чтобы вы знали, ну, сделайте это. Да, попытка опроса malloc может быть быстрой и простой, но знание n наверняка сведет к минимуму путаницу и усилит дизайн.

0 голосов
/ 19 сентября 2015

В uClibc , есть макрос MALLOC_SIZE в malloc.h:

/* The size of a malloc allocation is stored in a size_t word
   MALLOC_HEADER_SIZE bytes prior to the start address of the allocation:

     +--------+---------+-------------------+
     | SIZE   |(unused) | allocation  ...   |
     +--------+---------+-------------------+
     ^ BASE             ^ ADDR
     ^ ADDR - MALLOC_HEADER_SIZE
*/

/* The amount of extra space used by the malloc header.  */
#define MALLOC_HEADER_SIZE          \
  (MALLOC_ALIGNMENT < sizeof (size_t)       \
   ? sizeof (size_t)                \
   : MALLOC_ALIGNMENT)

/* Set up the malloc header, and return the user address of a malloc block. */
#define MALLOC_SETUP(base, size)  \
  (MALLOC_SET_SIZE (base, size), (void *)((char *)base + MALLOC_HEADER_SIZE))
/* Set the size of a malloc allocation, given the base address.  */
#define MALLOC_SET_SIZE(base, size) (*(size_t *)(base) = (size))

/* Return base-address of a malloc allocation, given the user address.  */
#define MALLOC_BASE(addr)   ((void *)((char *)addr - MALLOC_HEADER_SIZE))
/* Return the size of a malloc allocation, given the user address. */
#define MALLOC_SIZE(addr)   (*(size_t *)MALLOC_BASE(addr))
...