Как получить длину блока памяти после malloc?

Я думал, что не могу получить длину выделенного блока памяти, как простая функция .length в Java. Однако теперь я знаю, что когда malloc() выделяет блок, он выделяет дополнительные байты для хранения целого числа, содержащего размер блока. Это целое число расположено в начале блока; адрес, фактически возвращенный вызывающему, указывает на место, расположенное за этим значением длины. Проблема в том, что я не могу получить доступ к этому адресу, чтобы получить длину блока.

#include <stdlib.h>
#include <stdio.h>
int main(void)
{
        char *str;
        str = (char*) malloc(sizeof(char)*1000);
        int *length;
        length = str-4; /*because on 32 bit system, an int is 4 bytes long*/
        printf("Length of str:%d\n", *length);
        free(str);
}

** Edit: Наконец я это сделал. Проблема в том, что она продолжает давать 0, поскольку длина, а не размер в моей системе, связана с тем, что мой Ubuntu имеет 64 бит. Я изменил str-4 на str-8, и теперь он работает.

Если я изменю размер до 2000, он будет генерировать 2017 как длину. Однако, когда я перехожу на 3000, он дает 3009. Я использую GCC.

Ответ 1

То, что вы делаете, определенно неверно. Хотя он почти уверен, что слово непосредственно перед выделенным блоком связано с размером, даже если оно, вероятно, содержит некоторые дополнительные флаги или информацию в неиспользуемых битах. В зависимости от реализации эти данные могут быть даже в битах с высоким, что приведет к тому, что вы прочитаете совершенно неправильную длину. Также возможно, что небольшие распределения (например, от 1 до 32 байтов) упаковываются в специальные страницы с небольшим блоком без заголовков, и в этом случае слово перед выделенным блоком является частью другого блока и не имеет никакого значения в отношении размера блока, который вы изучаете.

Просто прекратите это ошибочное и опасное преследование. Если вам нужно знать размер блока, полученный с помощью malloc, вы делаете что-то неправильно.

Ответ 2

Вам не нужно отслеживать это самостоятельно!

size_t malloc_usable_size (void * ptr);

Но он возвращает реальный размер выделенного блока памяти! Не размер, который вы передали в malloc!

Ответ 3

Я предлагаю вам создать свою собственную оболочку malloc, компилируя и связывая файл, который определяет my_malloc(), а затем перезагружает значение по умолчанию следующим образом:

// my_malloc.c

#define malloc(sz) my_malloc(sz)

typedef struct {
    size_t size;
} Metadata;

void *my_malloc(size_t sz) {
    size_t size_with_header = sz + sizeof(Metadata);
    void* pointer = malloc(size_with_header);

    // cast the header into a Metadata struct
    Metadata* header = (Metadata*)pointer;
    header->size = sz;    
    // return the address starting after the header 
    // since this is what the user needs
    return pointer + sizeof(Metadata);
}

то вы всегда можете получить размер, выделенный путем вычитания sizeof (метаданные), наведя этот указатель на метаданные и сделав метаданные- > размер:

Metadata* header = (Metadata*)(ptr - sizeof(Metadata));
printf("Size allocated is:%lu", header->size); // don't quote me on the %lu ;-)

Ответ 4

Это не стандарт C. Однако предполагается, что он работает в системах Windows и может быть доступен в других операционных системах, таких как Linux (msize?) или Mac (alloc_size?), а также.

size_t _msize (void * memblock);

_msize() возвращает размер блока памяти, выделенного в куче.

Смотрите эту ссылку: http://msdn.microsoft.com/en-us/library/z2s077bc.aspx

Ответ 5

Ты не должен это делать. Если вы хотите узнать, сколько памяти вы выделили, вам нужно следить за ней самостоятельно.

Выглянув за пределы возвращенного вам блока памяти (до того, как указатель, возвращаемый malloc, или после этого указателя + количество запрошенных вами байтов) приведет к поведению undefined. Это может работать на практике для данной реализации malloc, но не стоит зависеть от этого.

Ответ 6

Это зависит от реализации

Ответ 7

Лучше перестань пытаться делать то, что тебе нужно!

AFAIK содержимое памяти до начала выделенного блока не определяется стандартом C/С++, поэтому вы получите непортативное решение. Вы должны сами отслеживать длину блока памяти.

Ответ 8

Запуск этого приложения в моей (Ubuntu) системе говорит:

Length of str:1009

Ответ 9

Каждому блоку, который вы назначаете, предшествует дескриптор блока. Проблема в том, что она зависит от архитектуры системы. Попробуйте найти размер дескриптора блока для вашей собственной системы. Попробуйте взглянуть на страницу системы malloc.