如何解除分配2d数组?

use*_*293 9 c arrays pointers

这已经有很多东西了.他们似乎都暗示你每次调用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++中,它更可以接受的使用newdelete语言,而不是传统的C类的东西的方面mallocfree.您已经提到的指南(确保delete每个指南都有new)仍然有效,但确保您delete[]在释放项目数组时使用的附加复杂性.

这不是说malloc,free也不会奏效; 它们仍然是C++语言规范的重要组成部分.只是C++的处理方式可以更加强大,因为它可以在一次命中中分配初始化对象,并在内存不足时引发异常,这意味着您不必通过NULL检查来查看代码.

此外,C++在其标准库中提供了大量的集合,这些集合使处理事务组比使用原始数组容易得多.其中一个是vector基本上可调整大小的数组,您应该考虑在以前使用过数组的情况下使用它.

您展示的代码将更容易实现为字符串向量(C++字符串,而不是那些微不足道的C字符串).而且,事实上,我会考虑更进一步,实际上将整个数据结构封装到自己的类中,隐藏它完全使用向量的事实.

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

  • 做C++的正确方法是"为了皮特的缘故2014年,使用`std :: vector`已经",而且我厌倦了将此评论留在其中包含"数组"的所有其他C++问题中.我想我可以找到一个很好的问题,这个问题已经接受了这个效果的答案,只是将它们全部作为重复,这是一个正确的举动吗? (5认同)
  • 这就是为什么留下这样的评论是有用的:它导致了这个答案的改进! (2认同)

lda*_*v1s 5

你没有为指针指针分配足够的空间.这个:

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++中完成同样的事情,以实现您真正想要做的事情.