C 如何取消分配2d数组?

C 如何取消分配2d数组?,c,arrays,pointers,C,Arrays,Pointers,这上面已经有很多东西了。它们似乎都表明,每次调用malloc时,您所需要做的就是释放它,并且可能最后释放“指针指针”的指针,这样您就不会在释放内存后引用它 例如,如果我有 int** myPtr 那我只需要 free(myPtr[j]) 对于每个j,在最终释放指针指针之前 free(myPtr) 酷。我已经在我的程序中做过几次了,它似乎工作得很好——除了一个例子。我试图找出这个病例的不同之处,我能够在一个最小的程序中复制症状 #include "stdafx.h" #include <

这上面已经有很多东西了。它们似乎都表明,每次调用malloc时,您所需要做的就是释放它,并且可能最后释放“指针指针”的指针,这样您就不会在释放内存后引用它

例如,如果我有

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;
}
#包括“stdafx.h”
#包括
签名字符**getPtr()
{
无符号字符n=10;
无符号字符k=2;
签名字符**myPtr=(签名字符**)malloc(n*sizeof(签名字符));
如果(myPtr==NULL){returnnull;}
for(无符号字符i=0;i对于(无符号字符k=0;k您需要为
有符号字符的
n
指针分配空间,而不是为n
有符号字符分配空间:

signed char** myPtr = (signed char**)malloc(n*sizeof(signed char*));
                                                               ^^^

您没有为指向指针的指针分配足够的空间。 这:

应该是:

signed char** myPtr = malloc(n*sizeof(signed char*));
signed char** myPtr = (signed char**)malloc(n*sizeof(signed char*));
//                                                              ^
//                                                      char POINTER
如果
malloc
失败,您也会在此处泄漏内存:

for (unsigned char i = 0; i < n; i++)
{
    myPtr[i] = (signed char*)malloc(k*sizeof(signed char)); 
    if (myPtr[i] == NULL) {return NULL;}
}
for(无符号字符i=0;i
<>我假设你希望C代码的C版本不是完全可移植到C++。也许C++中有一种更合适的方法来完成你真正想要做的事情。

< P>你应该使用:

signed char** myPtr = (signed char**)malloc(n*sizeof(signed char*));
                                                                ^^ The missing *
而不是

signed char** myPtr = (signed char**)malloc(n*sizeof(signed char));
否则,您没有为指针分配足够的内存

当然,您不应该强制转换
malloc
的返回值。这会导致问题。有关详细信息,请参阅

使用:

您当前的问题是以下几行:

signed char** myPtr = (signed char**)malloc(n*sizeof(signed char));
这是错误的,因为它为
n
字符分配了足够的空间。相反,它应该是:

signed char** myPtr = malloc(n*sizeof(signed char*));
signed char** myPtr = (signed char**)malloc(n*sizeof(signed char*));
//                                                              ^
//                                                      char POINTER
char
的大小通常小于指针的大小,但即使不是,也应该使用正确的类型。事实上,我倾向于使用以下形式,这样我就不必重复该类型(重复可能会在将来更改一个,而忘记另一个):


除了这个之外,你应该考虑你实际在编码的语言。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++中,使用<代码>新< /COD>和<代码>删除>代码>方面更容易接受,而不是使用传统的C类东西,如<代码> Malc C >代码>和<代码>免费>代码>。仍然有效,但在释放项目数组时确保使用

delete[]
会增加复杂性

<>这不是说<代码> Malc 和 Fuff< /Cord>不会工作;它们仍然是C++语言规范的一部分。只是C++的方式可以更强大,因为它可以同时分配和初始化对象,并在内存中引发异常,这意味着你不必胡椒。带有
NULL
检查的代码

另外,C++在标准库中提供了大量的集合,使得处理组比使用原始数组容易得多。其中一个是<代码> vector < /C>,基本上是一个可调整数组,并且在以前使用数组的情况下应该考虑使用它。

你所显示的代码将更容易实现为字符串的向量(C++字符串,而不是那些小C字符串)。事实上,我会考虑再向前走一步,实际上把整个数据结构封装到它自己的类中,隐藏它使用向量的事实。


如果您这样做了,并提供了所需的所有setter/getter方法,那么以后可以替换整个底层数据结构,而不会影响使用它的代码。

getPtr
中,您:

// 1 byte
malloc n*sizeof(signed char)
但您正在存储一个指向有符号字符的指针,该字符是32或64位、4或8字节

您可以通过以下方式进行修复:

signed char*  zz;
signed char** myPtr = (unsigned char)malloc(n*sizeof(zz));

最简单的方法是使用真正的2D数组,而不仅仅是指向数组的指针数组。您可以这样分配2D数组:

signed char (*myPtr)[k] = malloc(n*sizeof(*myPtr));
for (unsigned char j = 0; j < n; j++)
{
    for (unsigned char i = 0; i < k; i++)
    {
        myPtr[j][i] = 42; 
    }
}
使用此分配,您不需要循环到
malloc()
线阵列。您可以像这样直接使用2D阵列:

signed char (*myPtr)[k] = malloc(n*sizeof(*myPtr));
for (unsigned char j = 0; j < n; j++)
{
    for (unsigned char i = 0; i < k; i++)
    {
        myPtr[j][i] = 42; 
    }
}

<> P>学习C的数组语法指针确实很有帮助。<问题>:@ AlxRynod,这个问题也被标记为C++ + AlxRynod,如果这是在C++和C上运行的,因为OP有语言标记。它可能不应该被标记为C++。这是一个C问题还是一个C++问题。这是两种不同的语言,正确的答案取决于这个差别。我现在正在处理一个由C++文件组成的项目,但是如果C的答案不同,我也希望知道。在C++中,最好不要使用malloc函数族,有更好的选择。选择一种语言并坚持使用。如果你正在使用。