Char指针是结构体数组的内存泄漏问题。

4

我在一个较大的程序中遇到了内存泄漏问题,我认为这是导致问题的原因。

#include <stdlib.h>
#include <Windows.h>

typedef struct _struct{
    char* name;
} str;

int main() {
    system("PAUSE");

    str* Character = (str*)malloc(sizeof(str) * 20000);

    for(int i = 0; i < 20000; i++){
        Character[i].name = (char*)malloc(20000);   // Assign memory.
    }

    for(int i = 0; i < 20000; i++){
        free(Character[i].name);            // Free memory.
    }

    free(Character);
    system("PAUSE");
}

第一次暂停时的内存:约500K。

第二次暂停时的内存:约1.7M。

使用VS2012进行测试。有什么想法吗?


1
你的代码看起来正确。你是如何测量内存使用的?你的堆管理器是否在调用free后压缩了堆?如果是这种情况,额外的内存将被分配给你的进程,但不会被程序使用,因此实际上可以供其他代码分配使用。 - simonc
使用malloc时,请务必检查内存是否已分配:if(Character == NULL) - hazzelnuttie
你不应该对malloc的返回值进行强制类型转换。这是C语言,你可以将void指针赋值给任何类型。 - Tom Tanner
我也尝试了C++方法,使用了new char[]以及delete()。但是问题依旧出现 :/ - Marc
3个回答

4

你是如何测量程序占用的内存量的?我想到一个可能是,你正在查看操作系统跟踪的工作集的大小。由于你分配和释放了大量的内存,所以该集合的大小已经增加了。部分操作系统会在一段时间后调整工作集的大小,而有些则不会。请问我们现在考虑的是哪个操作系统?


我不确定Windows具体是如何操作的(稍后会检查,或者其他人可能会补充),但它可能不会显示您所期望的内容。现代操作系统以粗略和懒惰的方式管理进程内存以节省处理时间,并可能延迟页面的释放。malloc和free的实现也可能会保留内存。如果您真的想确保,可以使用像valgrind这样的工具来检查泄漏情况。 - idoby
我刚刚使用DrMemory运行了它,发现可能有3个(1536字节)泄漏,并且还有319个可达分配。 - Marc
当注释掉free时,程序结束时会分配更多的内存。而且在我的主程序中,为了实现特定目的,我需要使用mallocfree - Marc
不调用mallocfree进行测试,仅检查问题是否出在您的代码中。 - idoby
1
是一个操作系统问题。在Linux和Windows上进行了测试,循环运行并不会影响最终的内存值,同时在Linux和Windows上有不同的内存完成值。(抱歉回复晚了) - Marc
显示剩余4条评论

3
当您调用malloc时,内存将在堆上分配。如果堆剩余空间不足,程序将向操作系统请求更多内存并获得另一个块。从操作系统获得的内存通常在程序完成后才会被释放(尽管这取决于操作系统)。
仅通过程序大小通常无法检查内存泄漏!使用Valgrind或类似工具来检查从未被free的内存。

-1

str* Character = (str*)malloc(sizeof(str) * 20000);

在上述代码中,你通过查找结构体的大小来分配内存。这里你得到的结构体大小将是指针宽度的大小,而不是字符的大小。

例如,如果指针宽度为32位,则会分配(4 * 20000) = 80000字节。

如果你想要为20000个结构体分配内存,

str* Character = (str*)malloc(sizeof(char) * 20000);


1
str* Character是一个结构体数组,而不是字符(名称有点混淆,我同意),因此sizeof(str)是正确的。 - Joel Klinghed

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接