首页 > 解决方案 > 如何在使用自由函数之前清理 C 中分配的内存?

问题描述

我创建了一个名为employee 的嵌套结构。我使用malloc从堆中为员工分配空间。然后,我使用free释放空间。据我所知,free函数只标记了一个可用于未来分配的位置。因此,分配内存的内容保留在内存中,并导致堆检查。

我在程序开始时定义的结构如下。

struct address{
    char *city;
    int zip;
}

struct employee{
    char *name;
    struct address add;
}

我实现了一个名为 sanitize 的函数,用垃圾值替换私有字段(0xAA在本例中)。然后,我在 main 函数中测试了sanitize 。

void sanitize(char *ptr, int size){
    memset(ptr, 0xAA, size);
}

int main()
{
    struct employee* emp;
    emp = malloc(sizeof(char) * 40);
    emp->name = "John";
    emp->add.city = "London";
    emp->add.zip = 221;
    printf("%s\n", emp->add.city);
    sanitize(&(emp->add), sizeof(struct address));
    printf("%s\n", emp->add.city);
    return 0;
}

在运行时我得到分段错误。我的程序有什么问题?我应该如何以及以何种顺序清理嵌套结构?

提前致谢。

标签: cmemoryfreesanitization

解决方案


确保为您的对象正确分配内存。这样做的功能有很大帮助。

struct employee *new_employee()
{
  struct employee *emp = (struct employee*)malloc( sizeof(struct employee) );
  if (emp)
  {
    emp->name = NULL;
    emp->add.city = NULL;
  }
  return emp;
}

同样,创建一个销毁员工的函数:

struct employee *destroy_employee( struct employee *emp )
{
  if (emp)
  {
    if (emp->name)     free( emp->name );
    if (emp->add.city) free( emp->add.city );
    free( emp );
  }
  return NULL;
}

同样,您的清理功能需要了解员工:

void sanitize_employee( struct employee *emp )
{
  if (emp)
  {
    if (emp->name)     memset( emp->name,     0xAA, strlen( emp->name     ) );
    if (emp->add.city) memset( emp->add.city, 0xAA, strlen( emp->add.city ) );
    emp->add.zip = 0xAAAAAAAA;
  }
}

现在您可以轻松地创建和销毁员工:

struct employee *emp = new_employee();
emp->name = strdup( "John" );
emp->add.city = strdup( "London" );
emp->add.zip = 221;

...

sanitize_employee( emp );
emp = destroy_employee( emp );

请注意我们如何注意始终为每个对象分配空间,并适当地删除每个对象。您可以很好地结合消毒和销毁功能。

您的结构设计有一个重要问题。如果您更改员工的详细信息(例如,更改他的姓名),您的清理可能会失败,并且员工数据可能会未经清理。为此,您应该制定一个严格的政策,永远不要改变员工结构:使其成为 const,或创建额外的函数来改变数据并执行适当的清理和内存管理(清理、释放旧值、strdup新值)。

您可能只想创建一个固定大小的记录来处理员工数据。这将大大简化您的生活,并使您不必处理同样多的内存管理员工职能。


推荐阅读