user-0 提问: 二级指针无法释放

回复:
user: user-1
content: 楼主程序对内存释放部分应该没问题，至于在函数中设置 myarray = NULL 但是在main函数中myarray却不是NULL， 这点需要注意的是：函数形参传递的只是值而非变量地址，如果我们想更改该变量的值，需要把该变量的地址传递过去。

user: user-2
content: C语言是单向值传递，main函数中myarray的值并未改变，但个人觉得内存是释放了的。三级指针试试

user: user-3
content: if (myarray[i] != NULL)         {             free(myarray[i][]);         }

user: user-4
content: “free后，myarray的地址没有被释放”内存已经被释放了，只是myarray还是指向旧地址，但并不表明这块内存还可以用

user: user-5
content: 用三级指针吧。楼上的楼上。

user: user-6
content: 释放之后，需要指向NULL。 建议统一管理所用到的指针。

user: user-7
content: 内存释放不释放不是看指针是否为NULL的，把指针赋NULL只是为了说明此指针所指内存已不可用，防止非法访问。 对于你的释放函数，如果真的想把 myarray 的值传出去用于判断是否已释放内存的话的话，你应该用地址形式。  像如下一样：  /************************************************************************/ /* 释放内存                                                                     */ /************************************************************************/ void freeArray(char ***myarray,int n){     int i = 0;     if (*myarray == NULL){         return ;     }     for(i = 0; i < n;i++){          if ((*myarray)[i] != NULL)         {             free((*myarray)[i]);         }     }      if(*myarray != NULL){         free(*myarray);     }     *myarray = NULL; }  // 调用 freeArray(&myarray,10);

user: user-8
content: 执行完free函数之后，确实会将内存释放，但不会将myarray置为NULL，因为myarray存储在栈上，此时是一个野指针，需要手动置空。

user: user-9
content: 引用 楼主 laopufua 的回复:  #include <stdlib.h> #include <stdio.h> #include <string.h> /************************************************************************/ /* 分配内存                                                                     */ /************************************************************************/ char **arrayCreate(int n){ 	int i = 0; 	char **myarray = NULL; 	myarray = (char**)malloc(n*sizeof(char*)); 	if(myarray == NULL){ 		return NULL; 	} 	for(i = 0; i < 10; i++){ 		myarray[i] = (char*)malloc(10*sizeof(char)); 	} 	return myarray; }/************************************************************************/ /* 释放内存                                                                     */ /************************************************************************/ void freeArray(char **myarray,int n){ 	int i = 0; 	if (myarray == NULL){ 		return ; 	} 	for(i = 0; i < n;i++){  		if (myarray[i] != NULL) 		{ 			free(myarray[i]); 		} 	}  	if(myarray != NULL){ 		free(myarray); 	} 	myarray = NULL; }      int main(){ 	int n = 10; 	char **myarray = NULL; 	 	myarray = arrayCreate(10); 	freeArray(myarray,10); 	 	  	if (myarray == NULL){ 		printf("内存已经释放完毕！\n"); 	}  	system("pause");  }     断点调试，myarray分配内存后，可以获取地址，free后，myarray的地址没有被释放，还是之前的地址。指针传入参数后，执行后，不管用？传入的指针参数，无法修改吗？  楼主内存已经正确释放，问题仅仅出在参数传递上。  myarray 保存的是 分配的内存地址，释放这个内存之后要想改变myarray的值，要有myarray的地址。  也就是说改成：void freeArray(char ***myarray,int n);  把&myarray传递过去，函数最后*myarray = NULL，即可达成你想要的效果。

user: user-10
content: 仅供参考：#include <stdio.h> #include <stdlib.h> #include <malloc.h> int **newarr2d(int rows,int cols) {     int **p,i;      p=(int **)malloc(rows*sizeof(int *));     if (NULL==p) exit(1);     for (i=0;i<rows;i++) {         p[i]=(int *)malloc(cols*sizeof(int));         if (NULL==p[i]) exit(1);     }     return p; } void deletearr2d(int **p,int rows) {     int i;      for (i=0;i<rows;i++) {         free(p[i]);     }     free(p); } int main() {     int **arr2d,i,j,r,c;      r=4;     c=5;     //在堆中开辟一个4×5的二维int数组     arr2d=newarr2d(r,c);     for (i=0;i<r;i++) {         for (j=0;j<c;j++) {             arr2d[i][j]=i*c+j;         }     }     for (i=0;i<r;i++) {         for (j=0;j<c;j++) {             printf(" %2d",arr2d[i][j]);         }         printf("\n");     }     deletearr2d(arr2d,r);      r=6;     c=3;     //在堆中开辟一个6×3的二维int数组     arr2d=newarr2d(r,c);     for (i=0;i<r;i++) {         for (j=0;j<c;j++) {             arr2d[i][j]=i*c+j;         }     }     for (i=0;i<r;i++) {         for (j=0;j<c;j++) {             printf(" %2d",arr2d[i][j]);         }         printf("\n");     }     deletearr2d(arr2d,r);      return 0; } //  0  1  2  3  4 //  5  6  7  8  9 // 10 11 12 13 14 // 15 16 17 18 19 //  0  1  2 //  3  4  5 //  6  7  8 //  9 10 11 // 12 13 14 // 15 16 17 //