C++ 如何获取使用 malloc() 分配的内存块的大小?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1208644/
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-08-27 19:11:18  来源:igfitidea点击:

How can I get the size of a memory block allocated using malloc()?

c++cmemory-managementmalloc

提问by AndreasT

Possible Duplicates:
How can I get the size of an array from a pointer in C?
Is there any way to determine the size of a C++ array programmatically? And if not, why?

可能的重复:
如何从 C 中的指针获取数组的大小?
有没有办法以编程方式确定 C++ 数组的大小?如果不是,为什么?

I get a pointer to a chunk of allocated memory out of a C style function. Now, it would be really interesting for debugging purposes to know how big the allocated memory block that this pointer points is.

我从一个 C 风格的函数中得到一个指向一块已分配内存的指针。现在,知道这个指针指向的分配的内存块有多大对于调试来说真的很有趣。

Is there anything more elegant than provoking an exception by blindly running over its boundaries?

有什么比盲目越界引发异常更优雅的事情吗?

Thanks in advance, Andreas

提前致谢, 安德烈亚斯

EDIT:

编辑:

I use VC++2005 on Windows, and GCC 4.3 on Linux

我在 Windows 上使用 VC++2005,在 Linux 上使用 GCC 4.3

EDIT2:

编辑2:

I have _msizeunder VC++2005 Unfortunately it results in an exception in debug mode....

_msize在 VC++2005 下不幸的是它导致调试模式下的异常....

EDIT3:

编辑3:

Well. I have tried the way I described above with the exception, and it works. At least while I am debugging and ensuring that immediately after the call to the library exits I run over the buffer boundaries. Works like a charm.

好。我已经尝试过我上面描述的方法,但它确实有效。至少在我调试并确保在对库的调用退出后立即超出缓冲区边界时。奇迹般有效。

It just isn't elegant and in no way usable in production code.

它只是不优雅,也无法在生产代码中使用。

回答by Martin Beckett

It's not standard but if your library has a msize()function that will give you the size.

这不是标准的,但是如果您的库具有msize()可以为您提供大小的功能。

A common solution is to wrap mallocwith your own function that logs each request along with the size and resulting memory range, in the release build you can switch back to the 'real' malloc.

一个常见的解决方案是malloc使用您自己的函数进行包装,该函数记录每个请求以及大小和结果内存范围,在发布版本中,您可以切换回 'real' malloc

回答by Martin Beckett

If you don't mind sleazy violence for the sake of debugging, you can #define macros to hook calls to malloc and free and pad the first 4 bytes with the size.

如果您不介意为了调试而使用粗俗的暴力,您可以 #define 宏来挂钩对 malloc 和 free 的调用,并用大小填充前 4 个字节。

To the tune of

随心所欲

void *malloc_hook(size_t size) {
    size += sizeof (size_t);
    void *ptr = malloc(size);
    *(size_t *) ptr = size;
    return ((size_t *) ptr) + 1;
}

void free_hook (void *ptr) {
    ptr = (void *) (((size_t *) ptr) - 1);
    free(ptr);
}

size_t report_size(ptr) {
    return * (((size_t *) ptr) - 1);
}

then

然后

#define malloc(x) malloc_hook(x)

and so on

等等

回答by Greg Hewgill

The C runtime library does not provide such a function. Furthermore, deliberately provoking an exception will not tell you how big the block is either.

C 运行时库不提供这样的函数。此外,故意引发异常也不会告诉您块有多大。

Usually the way this problem is solved in C is to maintain a separate variable which keeps track of the size of the allocated block. Of course, this is sometimes inconvenient but there's generally no other way to know.

通常在 C 中解决这个问题的方法是维护一个单独的变量来跟踪分配的块的大小。当然,这有时不方便,但通常没有其他方法可以知道。

Your C runtime library mayprovide some heap debug functions that can query allocated blocks (after all, free()needs to know how big the block is), but any of this sort of thing will be nonportable.

您的 C 运行时库可能会提供一些可以查询已分配块的堆调试函数(毕竟,free()需要知道该块有多大),但任何此类东西都是不可移植的。

回答by Adrian Panasiuk

With gccand the GNU linker, you can easily wrap malloc

使用gccGNU linker,您可以轻松包装malloc

#include <stdlib.h>
#include <stdio.h>


void* __real_malloc(size_t sz);
void* __wrap_malloc(size_t sz)
{
    void *ptr;

    ptr = __real_malloc(sz);
    fprintf(stderr, "malloc of size %d yields pointer %p\n", sz, ptr);

    /* if you wish to save the pointer and the size to a data structure, 
       then remember to add wrap code for calloc, realloc and free */

    return ptr;
}

int main()
{
    char *x;
    x = malloc(103);

    return 0;
}

and compile with

并编译

gcc a.c -o a -Wall -Werror -Wl,--wrap=malloc

(Of course, this will also work with c++ code compiled with g++, and with the new operator (through it's mangled name) if you wish.)

(当然,这也适用于使用 g++ 编译的 c++ 代码,如果您愿意,也可以使用 new 运算符(通过它的错误名称)。)

In effect, the statically/dynamically loaded library will also use your __wrap_malloc.

实际上,静态/动态加载的库也将使用您的__wrap_malloc.

回答by Todd Gamblin

Memory checkers like Valgrind's memcheckand Google's TCMalloc(the heap checker part) keep track of this sort of thing.

Valgrind 的 memcheckGoogle 的 TCMalloc(堆检查器部分)等内存检查器会跟踪这类事情。

You can use TCMalloc to dump a heap profile that shows where things got allocated, or you can just have it check to make sure your heap is the same at two points in program execution using SameHeap().

您可以使用 TCMalloc 转储显示分配位置的堆配置文件,或者您可以使用SameHeap()检查以确保您的堆在程序执行的两个点相同。

回答by David Thornley

No, and you can't rely on an exception when overrunning its boundaries, unless it's in your implementation's documentation. It's part of the stuff you really don't need to know about to write programs. Dig into your compiler's documentation or source code if you really want to know.

不,并且您不能在超出其边界时依赖异常,除非它在您的实现文档中。这是编写程序时您真正不需要了解的内容的一部分。如果您真的想知道,请深入研究编译器的文档或源代码。

回答by bdonlan

There is no standard C function to do this. Depending on your platform, there may be a non-portable method - what OS and C library are you using?

没有标准的 C 函数可以做到这一点。根据您的平台,可能存在不可移植的方法 - 您使用的是什么操作系统和 C 库?

Note that provoking an exception is unreliable - there may be other allocations immediately after the chunk you have, and so you might not get an exception until long after you exceed the limits of your current chunk.

请注意,引发异常是不可靠的 - 在您拥有的块之后可能会立即有其他分配,因此在您超过当前块的限制很久之后,您可能不会收到异常。

回答by LaszloG

Partial solution: on Windows you can use the PageHeapto catch a memory access outside the allocated block.

部分解决方案:在 Windows 上,您可以使用PageHeap来捕获分配块之外的内存访问。

PageHeap is an alternate memory manager present in the Windows kernel (in the NT varieties but nobody should be using any other version nowadays). It takes every allocation in a process and returns a memory block that has its end aligned with the end of a memory page, then it makes the following page unaccessible (no read, no write access). If the program tries to read or write past the end of the block, you'll get an access violation you can catch with your favorite debugger.

PageHeap 是 Windows 内核中的替代内存管理器(在 NT 版本中,但现在没有人应该使用任何其他版本)。它获取进程中的每个分配并返回一个内存块,该内存块的末尾与内存页的末尾对齐,然后使下一页不可访问(无读,无写访问)。如果程序尝试读取或写入超过块的末尾,您将遇到访问冲突,您可以使用您最喜欢的调试器来捕获它。

How to get it: Download and install the package Debugging Tools for Windows from Microsoft: http://www.microsoft.com/whdc/devtools/debugging/default.mspx

如何获取:从 Microsoft 下载并安装 Windows 调试工具包:http: //www.microsoft.com/whdc/devtools/debugging/default.mspx

then launch the GFlags utility, go to the 3rd tab and enter the name of your executable, then Hit the key. Check the PageHeap checkbox, click OK and you're good to go.

然后启动 GFlags 实用程序,转到第 3 个选项卡并输入可执行文件的名称,然后单击该键。选中 PageHeap 复选框,单击 OK,您就可以开始了。

The last thing: when you're done with debugging, don't ever forget to launch GFlags again, and disable PageHeap for the application. GFlags enters this setting into the Registry (under HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\), so it is persistent, even across reboots.

最后一件事:完成调试后,永远不要忘记再次启动 GFlags,并为应用程序禁用 PageHeap。GFlags 将此设置输入注册表(在 HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\ 下),因此它是持久的,即使在重新启动后也是如此。

Also, be aware that using PageHeap can increase the memory needs of your application tremendously.

另外,请注意,使用 PageHeap 会极大地增加应用程序的内存需求。

回答by Christopher

The way to do what you want is to BEthe allocator. If you filter all requests, and then record them for debugging purposes, then you can find out what you want when the memory is free'd.

做你想做的事情的方法成为分配器。如果您过滤所有请求,然后将它们记录下来用于调试,那么您可以在释放内存时找出您想要的内容。

Additionally, you can check at the end of the program to see if all allocated blocks were freed, and if not, list them. An ambitious library of this sort could even take FUNCTIONand LINEparameters via a macro to let you know exactly where you are leaking memory.

此外,您可以在程序结束时检查是否所有分配的块都被释放,如果没有,则列出它们。这种雄心勃勃的库甚至可以通过宏获取FUNCTIONLINE参数,让您确切地知道内存泄漏的位置。

Finally, Microsoft's MSVCRT provides a a debuggable heap that has many useful tools that you can use in your debug version to find memory problems: http://msdn.microsoft.com/en-us/library/bebs9zyz.aspx

最后,Microsoft 的 MSVCRT 提供了一个可调试的堆,其中包含许多有用的工具,您可以在调试版本中使用这些工具来查找内存问题:http: //msdn.microsoft.com/en-us/library/bebs9zyz.aspx

On Linux, you can use valgrind to find many errors. http://valgrind.org/

在 Linux 上,您可以使用 valgrind 来查找许多错误。http://valgrind.org/