这已经有很多东西了.他们似乎都暗示你每次调用malloc时都需要做的就是免费调用,并且可能最后释放"指针指针" - 所以你不会在它被释放后最终引用它
例如,如果我有
int** myPtr
Run Code Online (Sandbox Code Playgroud)
然后我只需要
free(myPtr[j])
Run Code Online (Sandbox Code Playgroud)
对于每个j,在最终释放指针之前
free(myPtr)
Run Code Online (Sandbox Code Playgroud)
凉.我在我的程序中已经完成了几次,它似乎工作得很好 - 除了一个案例.我试图弄清楚这种情况有什么不同,我能够在最小的程序中复制症状.
#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;
}
Run Code Online (Sandbox Code Playgroud)
pax*_*blo 11
您的直接问题是以下行:
signed char** myPtr = (signed char**)malloc(n*sizeof(signed char));
Run Code Online (Sandbox Code Playgroud)
这是错误的,因为它为n 字符分配了足够的空间.相反,它应该是:
signed char** myPtr = (signed char**)malloc(n*sizeof(signed char*));
// ^
// char POINTER
Run Code Online (Sandbox Code Playgroud)
a的大小char通常小于指针的大小,但即使它不是,你应该使用正确的类型.事实上,我倾向于选择以下形式,以便我不必重复这种形式(重复有可能在将来改变一个,忘记另一个):
signed char** myPtr = (signed char**) malloc (n * sizeof (*myPtr));
Run Code Online (Sandbox Code Playgroud)
除此之外,您应该考虑您实际编写的语言.虽然C和C++分享了相当多的基本内容,但它们绝不是同一种语言,你编写代码的方式取决于你所针对的是哪一种.
让我们首先介绍C. 在该语言中,您不应该转换返回值,malloc因为它可以隐藏某些调试不太有趣的细微错误.放弃演员会给你:
signed char **myPtr = malloc (n * sizeof (*myPtr));
Run Code Online (Sandbox Code Playgroud)
另外,因为sizeof (char)(裸,有符号和无符号)总是一个,每当你看到自己乘以时,就更容易丢弃乘法.将其与之前的指南相结合,您可以转向:
myPtr[i] = (signed char*)malloc(k*sizeof(signed char));
Run Code Online (Sandbox Code Playgroud)
更可读:
myPtr[i] = malloc (k);
Run Code Online (Sandbox Code Playgroud)
现在,如果你正在为C++编写代码,还有其他一些事情要研究.
在C++中,它更可以接受的使用new和delete语言,而不是传统的C类的东西的方面malloc和free.您已经提到的指南(确保delete每个指南都有new)仍然有效,但确保您delete[]在释放项目数组时使用的附加复杂性.
这不是说malloc,free也不会奏效; 它们仍然是C++语言规范的重要组成部分.只是C++的处理方式可以更加强大,因为它可以在一次命中中分配和初始化对象,并在内存不足时引发异常,这意味着您不必通过NULL检查来查看代码.
此外,C++在其标准库中提供了大量的集合,这些集合使处理事务组比使用原始数组容易得多.其中一个是vector基本上可调整大小的数组,您应该考虑在以前使用过数组的情况下使用它.
您展示的代码将更容易实现为字符串向量(C++字符串,而不是那些微不足道的C字符串).而且,事实上,我会考虑更进一步,实际上将整个数据结构封装到自己的类中,隐藏它完全使用向量的事实.
如果您这样做,并提供所需的所有setter/getter方法,您可以稍后替换整个底层数据结构,而不会影响使用它的代码.
你没有为指针指针分配足够的空间.这个:
signed char** myPtr = (signed char**)malloc(n*sizeof(signed char));
Run Code Online (Sandbox Code Playgroud)
应该:
signed char** myPtr = malloc(n*sizeof(signed char*));
Run Code Online (Sandbox Code Playgroud)
如果malloc失败,你也会泄漏内存:
for (unsigned char i = 0; i < n; i++)
{
myPtr[i] = (signed char*)malloc(k*sizeof(signed char));
if (myPtr[i] == NULL) {return NULL;}
}
Run Code Online (Sandbox Code Playgroud)
我有点假设您希望此代码的C版本不能完全移植到C++.可能有更合适的方法在C++中完成同样的事情,以实现您真正想要做的事情.