如何在malloc之后获得内存块长度?

时间:2011-03-27 17:54:59

标签: c malloc

我认为我无法像Java中的简单.length函数那样检索已分配内存块的长度。但是,我现在知道当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);
}

**编辑: 我终于做到了。问题是,它持续给出0作为长度而不是我的系统上的大小是因为我的Ubuntu是64位。我将str-4更改为str-8,现在可以正常工作。

如果我将大小更改为2000,则会生成2017年的长度。但是,当我更改为3000时,它会给出3009.我正在使用GCC。

9 个答案:

答案 0 :(得分:25)

您不必自己跟踪它!

size_t malloc_usable_size(void * ptr);

但它返回分配的内存块的实际大小! 不是你传给malloc的大小!

答案 1 :(得分:15)

你所做的绝对是错的。虽然几乎可以肯定,在分配的块之前的字与大小有关,但即使如此,它可能在未使用的位中包含一些额外的标志或信息。根据实现情况,此数据甚至可能位于位,这会导致您读取完全错误的长度。此外,有可能将小分配(例如1到32个字节)打包到没有标题的特殊小块页面中,在这种情况下,分配块之前的单词只是另一个块的一部分,并且对于大小没有任何意义您要检查的区块。

请停止这种被误导和危险的追求。如果您需要知道malloc获得的块的大小,那么您做错了。

答案 2 :(得分:13)

我建议您通过编译和链接定义my_malloc()的文件然后覆盖默认值来创建自己的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 ;-)

答案 3 :(得分:7)

这不是标准C.但是,它应该适用于Windows操作系统,并且可能在其他操作系统上可用,例如Linux(msize?)或Mac(alloc_size?)。

size_t _msize(void * memblock);

_msize()返回堆中分配的内存块的大小。

查看此链接: http://msdn.microsoft.com/en-us/library/z2s077bc.aspx

答案 4 :(得分:6)

你不应该这样做。如果你想知道你分配了多少内存,你需要自己跟踪它。

查看返回给你的内存块之外(在malloc返回指针之前,或者在指针之后+你要求的字节数)将导致未定义的行为。对于给定的malloc实现,它可能在实践中有效,但依赖于它并不是一个好主意。

答案 5 :(得分:4)

这是依赖于实现的

答案 6 :(得分:2)

你最好不要试图做你正在做的事情!

AFAIK在分配块开始之前的内存内容未由C / C ++标准定义,因此最终会得到一个不可移植的解决方案。您必须自己跟踪内存块的长度。

答案 7 :(得分:1)

在我的(Ubuntu)系统上运行此应用程序说:

Length of str:1009

答案 8 :(得分:0)

您要分配的每个块都以块描述符开头。问题是,它取决于系统架构。 尝试为您自己的系统找到块描述符大小。试试看看你的系统malloc手册页。