C语言 malloc后如何获取内存块长度?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5451104/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 08:10:49  来源:igfitidea点击:

How to get memory block length after malloc?

cmalloc

提问by Amumu

I thought that I couldn't retrieve the length of an allocated memory block like the simple .lengthfunction in Java. However, I now know that when malloc()allocates the block, it allocates extra bytes to hold an integer containing the size of the block. This integer is located at the beginning of the block; the address actually returned to the caller points to the location just past this length value. The problem is, I can't access that address to retrieve the block length.

我认为我无法像.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);
}

**Edit: I finally did it. The problem is, it keeps giving 0 as the length instead of the size on my system is because my Ubuntu is 64 bit. I changed str-4 to str-8, and it works now.

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

If I change the size to 2000, it produces 2017 as the length. However, when I change to 3000, it gives 3009. I am using GCC.

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

采纳答案by R.. GitHub STOP HELPING ICE

What you're doing is definitely wrong. While it's almost certain that the word just before the allocated block is related to the size, even so it probably contains some additional flags or information in the unused bits. Depending on the implementation, this data might even be in the highbits, which would cause you to read the entirely wrong length. Also it's possible that small allocations (e.g. 1 to 32 bytes) are packed into special small-block pages with no headers, in which case the word before the allocated block is just part of another block and has no meaning whatsoever in relation to the size of the block you're examining.

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

Just stop this misguided and dangerous pursuit. If you need to know the size of a block obtained by malloc, you're doing something wrong.

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

回答by Informate.it

You don't have to track it by your self!

您不必自己跟踪它!

size_t malloc_usable_size (void *ptr);

size_t malloc_usable_size (void *ptr);

But it returns the real size of the allocated memory block! Not the size you passed to malloc!

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

回答by Mike M

I would suggest you create your own malloc wrapper by compiling and linking a file which defines my_malloc() and then overwiting the default as follows:

我建议您通过编译和链接定义 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);
}

then you can always retrieve the size allocated by subtracting sizeof(Metadata), casting that pointer to Metadata and doing metadata->size:

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

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

回答by Indinfer

This is not Standard C. However, it is supposed to work on Windows operatings systems and might to be available on other operating systems such as Linux (msize?) or Mac (alloc_size?), as well.

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

size_t _msize( void *memblock );

size_t _msize(void *memblock);

_msize() returns the size of a memory block allocated in the heap.

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

See this link: http://msdn.microsoft.com/en-us/library/z2s077bc.aspx

请参阅此链接:http: //msdn.microsoft.com/en-us/library/z2s077bc.aspx

回答by metamatt

You're not supposed to do that. If you want to know how much memory you've allocated, you need to keep track of it yourself.

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

Looking outside the block of memory returned to you (before the pointer returned by malloc, or after that pointer + the number of bytes you asked for) will result in undefined behavior. It might work in practice for a given malloc implementation, but it's not a good idea to depend on that.

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

回答by BlackBear

This is implementation dependent

这是依赖于实现的

回答by trenki

You better stop trying to do what you are up to!

你最好停止尝试做你想做的事!

AFAIK the contents of the memory before the beginning of the allocated block are not defined by the C/C++ standard, so you would end up with an unportable solution. You have to track the length of the memory block yourself.

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

回答by karlphillip

Running this app on my (Ubuntu) system says:

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

Length of str:1009

回答by Oleiade

Every block you're allocating is precedeed by a block descriptor. Problem is, it dependends on system architecture. Try to find the block descriptor size for you own system. Try take a look at you system malloc man page.

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