繁体   English   中英

释放动态分配的指针数组

[英]Freeing an array of dynamically allocated pointers

我正在为考试而学习,但是我对所提供的示例问题有疑问:

用原型void free_array(void *a[], int length)实现函数free_array。 该函数的目的是释放传递给函数的第一个参数中与每个数组元素关联的动态分配的内存。 该函数必须处理两个或更多个数组项指向同一内存的情况(单个内存位置只能使用一个空闲空间)。

我的第一个想法是将每个释放的索引设置为NULL,因为在NULL上调用free()是无害的。 所以我做了以下事情:

void free_array(void *a[], int length) { 
   int i;
   for (i = 0; i < length; i++) {
      free(a[i]);
      a[i] = NULL;
   }
}

提供的解决方案与我的解决方案完全不同,我不完全了解他们在做什么。 这是我得到的答案:

void free_array(void *a[], int length) { 
    int i, j;
    for (i = 0; i < length; i++) {
        if (a[i] != NULL) {
            free(a[i]);
            for (j = i + 1; j < length; j++) {
                if (a[j] == a[i]) {
                    a[j] = NULL;
                }
            }
        }
    }
}

我对这里发生的事情感到非常困惑。 似乎他们正在释放每个条目并将具有相同内容的条目标记为NULL。 但是,我认为我们不应该重新访问释放的内存吗? 另外,我的方式仍然有效吗?

该代码的目的是数组中的多个位置可以指向同一元素,但只能释放一次。 内部循环会将指向同一内存块的尚未处理的指针设置为指向null,从而不会尝试释放它们两次。

然而,与实施严重的问题:C标准说 free(x)的值x变得不确定 “不确定”表示在检查变量的任何情况下该值都可以是任何值。 因此,对于C编译器而言,假定该指针与任何有效指针的指针不匹配并优化“几乎正确”是合法的

void free_array(void *a[], int length) {
   int i, j;
   for (i = 0; i < length; i++) {
      if (a[i] != NULL) {
          free(a[i]);
          for (j = i + 1; j < length; j++) {
              if (a[j] == a[i]) {
                  a[j] = NULL;
              }
           }
     }
}

void free_array(void *a[], int length) {
    int i, j;
    for (i = 0; i < length; i++) {
        if (a[i] != NULL) {
            free(a[i]);
            for (j = i + 1; j < length; j++) {
                if (false) {
                }
            }
        }
    }
}

void free_array(void *a[], int length) {
    int i, j;
    for (i = 0; i < length; i++) {
        if (a[i] != NULL) {
            free(a[i]);
        }
    }
}

正确的解决方案必须调用free 之前进行指针比较:

void free_array(void *a[], int length) {
    int i, j;
    for (i = 0; i < length; i++) {
        if (a[i] != NULL) {
            for (j = i + 1; j < length; j++) {
                if (a[j] == a[i]) {
                    a[j] = NULL;
                }
            }
            free(a[i]);
        }
    }
}

例如

说你有一个字符串数组

char* ar[5]; 

您分配一些字符串,并让0和4索引指向同一分配的字符串

ar[0] = ar[4] = strdup("mycommonstring");
ar[1] = strdup("hello");
ar[2] = strdup("world");
ar[3] = strdup("!");

使用您的答案,您将首先释放ar [0]指向的内容,不幸的是ar [4]仍指向相同的内存位置,但是当调用free(ar[0]) ,它指向的内存位置无效。 稍后在ar [4]上调用free时,将导致错误。

给定的示例确保将所有指向同一位置的指针设置为NULL,以避免将无效地址传递给free函数。 因此,不可以,不能再次访问该存储位置,只能访问该存储位置的指针

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM