如何清理C中分配的内存?

时间:2014-04-24 22:57:08

标签: c memory malloc

我编写了以下玩具程序并观察到第二个变量 test2 将采用第一个变量 test1 释放的内存地址。即使我自由(test1),test2也会保留test1的字段值。我想知道如何清理C中的free()留下的数据:

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

typedef struct test_str
{
    char name[128];
    int Id;
} test_str;

typedef test_str* mytest;

int main()
{

    mytest test1 = malloc(sizeof(test_str));
    printf("test1 pointer address is %p \n", test1);
    strcpy(test1->name, "hello world");
    test1->Id = 10;

    free(test1);
//  test1->name = NULL;   /* this does not work */
//  test1->Id = 0;        /* without resetting Id = 0, test2->Id will show 10 */
    test1 = NULL;         

    mytest test2 = malloc(sizeof(test_str));
    printf("test2 pointer address is %p, name field is %s, Id = %d \n", test2, test2->name, test2->Id);

    return 0;
}

这是输出:

  

test1指针地址为0x2401010
  test2指针地址为0x2401010,名称字段为hello world,Id = 10

6 个答案:

答案 0 :(得分:3)

如果您的数据非常敏感,请使用平台调用来固定内存,并使用对某些memset - 变体的非线性调用,以便在免费之前清除。

当您将内存返回给运行时时,可以将其用于下一个拟合请求。它是否以及何时这样做,或者是否将内存恢复到可能的操作系统,并不是标准规定的。

除此之外:void free(void*) {}free的有效实现。

答案 1 :(得分:2)

地球上几乎没有任何理由可以做到这一点......

然而,在test1->name[0]=0之前添加free(test1)应该可以胜任。

如果你想删除&#34;所有追踪&#34;在上一篇文章中,您甚至可以这样做:

for (int i=0; test1->name[i]!=0; i++)
    test1->name[i]=0;

答案 2 :(得分:1)

正如评论中所提到的,只需在memset之前使用free

memset(test1, 0, sizeof(*test1));
free(test1);

答案 3 :(得分:1)

free()不会清除内存意义上的归零 - 它只是让它可以重用 - 而这正是这里发生的事情。如果您的意图是初始化已分配的内存,请考虑使用calloc()。

答案 4 :(得分:1)

你可以在释放之前使用memset(test1, 0, sizeof(test_str)),这只会将分配的内存区域填充为0。

malloc算法实际上通过保留它创建的每个内存块的元数据来工作。因此,如果您刚刚分配/释放/重新分配相同的大小,您可能会使用完全相同的内存块,这可以解释为什么新地址是相同的。

答案 5 :(得分:1)

一般来说,C函数不会做任何事情,除了他们应该做的事情。 mallocfree只是分配并释放内存 - 仅此而已。这意味着他们不会删除任何字段。

创建结构时,一般技术是清理任何相关字段。实际上,考虑编写一个封装结构创建的函数,如下所示:

mytest create_struct(char* name, int id) {
    mytest t = malloc(sizeof(test_str));
    size_t nlen = strlen(name);
    memcpy(t->name, name, nlen <= 127 ? nlen : 127);
    t->name[127] = '\0';

    t->Id = id;
    return t;
}

如果您愿意,还可以考虑定义相应的删除功能。

void del_struct(mytest t) {
    if (t) {
        memset(t->name, 0, 128);
        t->Id = 0;
        free(t);
    }
}