c - 如何释放二维数组?

标签 c arrays pointers

这方面已经有很多东西了。他们似乎都建议您需要做的就是在每次调用 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[] 会增加复杂性。释放项目的数组时。

这不是说mallocfree不会工作;它们仍然是 C++ 语言规范的重要组成部分。只是 C++ 做事的方式可以更强大,因为它可以一次性分配 初始化对象,并在内存不足时引发异常,这意味着你没有用 NULL 填充你的代码检查。

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

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

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

关于c - 如何释放二维数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26008416/

相关文章:

sql - 关于代码片段的解释

c - 如何为 10 名学生的结构生成随机 ID 和测试分数

php - 将两个或多个简单数组转换为多维数组?

c - strlen() 没有给出正确的值?

c - 这是一个有效的 C ifdef 结构吗?有没有更好的办法?

java - 如何将字符串中的字符转换为数字(转换为电话号码)?

arrays - 在 Go 中初始化数组时使用 spread

c++ - 为什么我在声明中说 int *p = NULL ,但在测试中说 p != NULL ,为什么 *p != NULL 不匹配声明?

c++ - 如何创建对象变量以便每次都分配新的指针?

c++ - 代码解释 c++ [struct/two diamentinal array/pointers]