如何在C中正确释放char **

我真的对这个2D char数组感到困惑

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); 

没有

 while(*tmp != NULL){ 

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

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

正如其他人所说,如图所示在循环中释放的问题是需要分配额外的项(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); 

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

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

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

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

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

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