【问题标题】:Memory Leak Struct char C内存泄漏结构字符 C
【发布时间】:2018-02-08 00:26:05
【问题描述】:

我想我这里有一些内存泄漏。
也许有人可以告诉我在这种情况下如何处理泄漏的正确方法。

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

struct adresse {
    char *name;
    int nummer;
};

int main() {

    int size = 2;
    struct adresse *a = (struct adresse *) malloc(sizeof(struct adresse) * size);

    for (int i = 0; i < size; i++) {
        a[i].name = "Testname";
        a[i].nummer = 123;
    }

    for (int i = 0; i < size; i++) {
        printf("%s, %d\n", a[i].name, a[i].nummer);
    }

    free(a);

    return 0;
}

【问题讨论】:

  • 为什么你认为这里有内存泄漏?
  • 为什么你认为你有内存泄漏?我看到的唯一问题是您没有检查malloc 返回NULL。除此之外,代码看起来还可以。
  • @immibis 可能是因为结构中的字符
  • 你不能free "Testname" 因为它是一个字符串文字。 struct 成员只包含一个指针。
  • 打扰一下,但健壮的代码应该检查所有函数的返回值,为您的利益提供。 NULL 这里的意思是没有可用的内存。

标签: c memory struct


【解决方案1】:

我想我这里有一些内存泄漏。也许有人可以告诉我在这种情况下如何处理泄漏的正确方法。

在您编写的任何动态分配内存的代码中,对于分配的任何内存块,您都有 2 个职责:(1)始终保留指向起始地址的指针内存块,因此,(2) 当不再需要它时可以释放

如果您分配它,请跟踪它,并在不再需要它时free 它。如果你没有分配它,你不能free它。如果你已经释放它,你不能再次free它。

" 如果参数与内存管理函数先前返回的指针不匹配,或者如果空间已通过调用 free 或 realloc 被释放,则行为未定义。"

C11 §7.22.3.3 The free function [p2] (n1570 draft)

你唯一分配的是a,然后你释放a -- 你没有内存泄漏

内存使用/错误检查示例

您可以通过使用内存使用/错误检查程序(例如 Linux 上的valgrind -- 每个操作系统都有类似的程序)轻松确认是否存在内存泄漏。它们使用简单,只需通过它运行您的程序即可:

$ valgrind ./bin/leak
==23745== Memcheck, a memory error detector
==23745== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==23745== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==23745== Command: ./bin/leak
==23745==
Testname, 123
Testname, 123
==23745==
==23745== HEAP SUMMARY:
==23745==     in use at exit: 0 bytes in 0 blocks
==23745==   total heap usage: 1 allocs, 1 frees, 32 bytes allocated
==23745==
==23745== All heap blocks were freed -- no leaks are possible
==23745==
==23745== For counts of detected and suppressed errors, rerun with: -v
==23745== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

始终确认您已释放所有已分配的内存并且没有内存错误。

(注意,取决于您的操作系统和valgrind 的实现,它可能会显示系统为您的进程分配的内存在程序退出时仍在使用。并非所有valgrind 的实现提供适当的抑制文件来屏蔽操作系统为您的进程而不是您分配的所有内存。只要您确认您分配的内存已被释放 - 您已经完成了您的工作。)

从上面的valgrind 输出中可以看出,您没有错误,并且所有分配的内存都已释放。 (干得好!)

【讨论】:

  • 一个奇怪问题的好答案。通常我们会收到诸如“我的代码不起作用”之类的问题,然后他们会发布疯狂泄露的代码。这次正好相反。
  • 是的,由于某种原因动态分配内存,它的管理对于那些学习 C 的人来说似乎是一个绊脚石。书籍涵盖了它,但绝大多数人(包括我)在第一次阅读它之后时间,这不是我觉得完全舒服的事情。在使用它几次之后,你会发现它真的很简单,但它通常不会以一种在第一次阅读时传达这种理解的方式呈现。可能是因为指针和内存分配分开了 4 章,没有参考标准或内存检查程序。
  • 是的,一开始我在指针和内存分配方面也遇到了不少麻烦。我没有从书本上学到太多,但我练习了很多。在某些时候,你就会明白。
【解决方案2】:

您也应该 malloc 测试名称字符串。这使得释放所有内容变得更加复杂,因为您需要先释放所有 Testname 字符串,然后释放整个结构内存。

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

struct adresse {
  char *name;
  int nummer;
};

int main() {

    int size = 2;
    struct adresse *a = (struct adresse *) malloc(sizeof(struct adresse) * size);

    for (int i = 0; i < size; i++) {
      char *str = "Testname";
      size_t len = strlen(str);
      a[i].name = malloc(len+1);
      memset(a[i].name, 0, len+1);
      memcpy(a[i].name, str, len);
      a[i].nummer = 123;
    }

    for (int i = 0; i < size; i++) {
        printf("%s, %d\n", a[i].name, a[i].nummer);
        free(a[i].name);
    }

    free(a);

    return 0;
}

【讨论】:

  • 这无缘无故地让程序变得更加复杂。它也没有回答问题。
  • 如果他希望最终能够修改 name 指向的数据,这是正确的。这取决于他对这些数据的最终用途。
  • @StephenDocy 这不一定是真的他还可以设置在main 中声明和初始化的char 数组的指针。即使不使用malloc,您也可以修改它们。
  • @Snohdo 仅仅因为你看到了char*,并不意味着你必须使用malloc。在您的代码中,您至少可以修复第一个malloc,您不应该强制转换它,最好的做法是执行malloc(size * sizeof *a)
猜你喜欢
  • 2011-05-04
  • 2014-09-25
  • 2016-03-28
  • 1970-01-01
  • 1970-01-01
  • 2011-10-04
  • 1970-01-01
  • 2014-04-30
  • 1970-01-01
相关资源
最近更新 更多