这方面已经有很多东西了。他们似乎都建议您需要做的就是在每次调用 malloc 时调用 free,并且可能最后释放“指针的指针”——这样您就不会在内存被释放后引用该内存
例如,如果我有
int** myPtr
那我只需要
free(myPtr[j])
对于每个j,在最终释放指针的指针之前
free(myPtr)
很酷。我已经在我的程序中这样做了几次,它似乎工作得很好——除了一个案例。我试图弄清楚这个案例有什么不同,并且我能够在一个最小的程序中复制这个症状。
#include "stdafx.h"
#include <stdlib.h>
signed char** getPtr()
{
unsigned char n = 10;
unsigned char k = 2;
signed char** myPtr = (signed char**)malloc(n*sizeof(signed char));
if (myPtr == NULL) {return NULL;}
for (unsigned char i = 0; i < n; i++)
{
myPtr[i] = (signed char*)malloc(k*sizeof(signed char));
if (myPtr[i] == NULL) {return NULL;}
}
for (unsigned char j = 0; j < n; j++)
{
for (unsigned char k = 0; k <= 1; k++)
{
myPtr[j][k] = 42;
}
}
return myPtr;
}
int _tmain(int argc, _TCHAR* argv[])
{
signed char** potato = getPtr();
if (potato != NULL)
{
for (unsigned char j = 0; j < 10; j++)
{
free(potato[j]);
}
free(potato);
}
return 0;
}
最佳答案
您的直接问题是以下行:
signed char** myPtr = (signed char**)malloc(n*sizeof(signed char));
这是错误的,因为它为 n
分配了足够的空间字符。相反,它应该是:
signed char** myPtr = (signed char**)malloc(n*sizeof(signed char*));
// ^
// char POINTER
char
的大小通常小于指针的大小,但即使不是,您也应该使用正确的类型。事实上,我倾向于更喜欢下面的形式,这样我就不必重复类型(重复有可能我以后可能会更改一个而忘记另一个):
signed char** myPtr = (signed char**) malloc (n * sizeof (*myPtr));
除此之外,您还应该考虑您实际编码的语言。尽管 C 和 C++ 共享相当多的基本内容,但它们绝不是同一种语言,您编写代码的方式取决于您的目标语言。
让我们先介绍C。在那种语言中,您不应该从 malloc
转换返回值因为它可以隐藏某些调试起来不有趣的细微错误。放下类型转换给你:
signed char **myPtr = malloc (n * sizeof (*myPtr));
此外,由于 sizeof (char)
(裸、有符号和无符号)始终是一个,每当您看到自己乘以它时,就更容易放弃乘法。将其与之前的指南相结合,您可以:
myPtr[i] = (signed char*)malloc(k*sizeof(signed char));
进入更具可读性:
myPtr[i] = malloc (k);
现在,如果您正在为 C++ 编写代码,则还有其他事项需要研究。
在 C++ 中,使用 new
更容易被接受和 delete
语言方面而不是像 malloc
这样的遗留 C 东西和 free
.您已经提到的准则(确保每个 delete
都有一个 new
)仍然有效,但确保您使用 delete[]
会增加复杂性。释放项目的数组时。
这不是说malloc
和 free
不会工作;它们仍然是 C++ 语言规范的重要组成部分。只是 C++ 做事的方式可以更强大,因为它可以一次性分配 和 初始化对象,并在内存不足时引发异常,这意味着你没有用 NULL
填充你的代码检查。
此外,C++ 在其标准库中提供了大量的集合,这使得处理成组的事物比使用原始数组容易得多。其中之一是 vector
,基本上是一个可调整大小的数组,您应该考虑在您以前可能使用过数组的情况下使用它。
您展示的代码作为字符串 vector (C++ 字符串,而不是那些微不足道的 C 字符串)实现起来会容易得多。而且,事实上,我会考虑更进一步,将整个数据结构封装到它自己的类中,完全隐藏它使用 vector 的事实。
如果您这样做,并提供您需要的所有 setter/getter 方法,您以后可以替换整个底层数据结构, 不会影响使用它的代码。
关于c - 如何释放二维数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26008416/