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

Amu*_*umu 16 c malloc

我以为我无法像.lengthJava中的简单函数那样检索分配的内存块的长度.但是,我现在知道,在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);
}
Run Code Online (Sandbox Code Playgroud)

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

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

小智 25

你不必自己跟踪它!

size_t malloc_usable_size(void*ptr);

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

  • 重要的是要注意,此函数不是C标准的一部分,并且是gnulib扩展 (6认同)

R..*_*R.. 16

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

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

  • 我知道了.谢谢.这就是为什么它对每种尺寸都有不同的价值.我只是试着看看它是如何工作的,我不会在现实中做到这一点.但是,书中的练习需要根据其解释的实现来实现malloc()和free(),所以我只想试一试. (2认同)
  • 绝大多数unix系统的`sizeof(int)`总是4,而且可能永远都是.如果你想要系统字大小,请使用`long`或更好的`size_t`. (2认同)

Mik*_*e M 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);
}
Run Code Online (Sandbox Code Playgroud)

然后你总是可以通过减去sizeof(元数据)来检索分配的大小,将指针转换为元数据并执行元数据 - >大小:

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

  • 值得注意的是,您的包装器返回的内存将不再在大多数体系结构上对齐.我应该知道,我写了同样的东西,依靠对齐的代码在我脸上爆炸了. (2认同)

小智 7

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

size_t _msize(void*memblock);

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

请看这个链接:http: //msdn.microsoft.com/en-us/library/z2s077bc.aspx


met*_*att 6

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

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