【问题标题】:How to properly free char** in C如何在 C 中正确释放 char**
【发布时间】:2015-10-11 13:00:25
【问题描述】:

我真的对这个二维字符数组感到困惑

char **arg = malloc(sizeof(char*) * argc)
for (int i = 0; i < argc; i++)
  arg[i] = malloc(sizeof(char) * size)
...
...

现在假设经过一系列操作,我忘记了变量 argc,如何释放这些内存? 我可以做这样的事情吗?这在所有情况下都绝对正确吗?

char **tmp = arg;
while (*tmp != NULL){
    free(*tmp); 
    tmp++;
}
free(arg);

【问题讨论】:

  • 数组不以 NULL 结尾,仅对字符串有效(C 中的 char *)
  • 您实际上是在为 char* 数组分配内存,然后为数组中的每个项目分配内存。你必须先释放项目然后释放它自己的数组。
  • 这实际上不是一个坏主意,但您应该在数组末尾显式放置一个NULL。我在很多情况下都使用它,它很好。
  • 这不是二维数组,而是指针的指针。
  • 其实 arg 是一个 char* 的动态数组;可以容纳(argc)元素;元素是可以容纳(大小)字符的动态字符数组;每个数组和元素分别被释放;

标签: c pointers


【解决方案1】:

没有

while(*tmp != NULL){

您可能会达到一个点,您将取消引用尚未分配的内存并触发未定义的行为。

或者按照建议,您可以将NULL 显式分配给最后分配的指针,在这种情况下它将起作用。

【讨论】:

  • @lplouis:跟踪您已分配内存的指针数量
  • 所以不能忘记argc?
  • @lplouis 或者,分配argc + 1 指针并手动将最后一个设置为NULL
  • 即使在最后添加NULL 也可以,但更好的方法是for (int i = 0 ; arg[i] != NULL ; ++i),这样就不需要tmp
【解决方案2】:

正如其他人所说,在循环中释放的问题是需要分配一个额外的项目 (argc + 1) 并且必须将其设置为 NULL。另一种技术是首先为指针分配空间

char **arg = malloc(sizeof(char*) * argc)

然后,如果您知道所有后续项目的大小相同,请将其分配在一个巨大的块中,并将其余元素设置为间隔偏移量

arg[0] = malloc(sizeof(char) * size * argc);
for (int i = 1; i < argc; ++i)
   arg[i] = arg[i - 1] + size;

释放空间是一件轻而易举的事:甚至不需要记住 argc

free(arg[0]); /* this will free the memory used by all the elements */
free(arg);

这种技术的最大缺点是如果任何数组元素溢出,它将破坏下一项。除非它是最后一项,否则无法通过堆检查轻松检测到这一点。

【讨论】:

    【解决方案3】:

    如果你像这样定义你的 char * 数组:

    char **arg = calloc( 1, sizeof( char * ) * argc );

    您可以确定每个未定义的指针都等于 NULL

    然后你就可以像你建议的那样使用 while 循环了:

    char *tmp = *arg;
    while ( tmp != NULL ) {
        free( tmp ); 
        tmp++;
    }
    free(arg);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-11-15
      • 1970-01-01
      • 1970-01-01
      • 2011-11-11
      • 2015-05-10
      • 1970-01-01
      • 2014-01-25
      • 1970-01-01
      相关资源
      最近更新 更多