C语言 释放矩阵,在这种情况下自由如何工作



我有一个矩阵动态分配的char或其他类似的东西:

char **ptr;
ptr = (char**)malloc(sizeof(char*) * 3);
*ptr = (char*)malloc(4);
*(ptr + 1) = (char*)malloc(4);
*(ptr + 2) = 0;

如果我在不释放指针的内存的情况下释放矩阵行

int i;
for(i = 0; i < 2; i++)
free(*(ptr + i));

将释放空指针之前最后一个行旁边的所有行,在这种情况下,将仅释放 *ptr 行。 要免费和最后一个,我们需要再添加一条指令

free(ptr);

问题是它的工作原理是什么,为什么我们不能只释放指针内存或只释放该矩阵的字符串内存?

我相信你考虑内存分配的方式有两个问题。

首先,您似乎认为矩阵被分配在内存中作为可视矩阵。但是您必须记住,编译器没有矩阵的概念。它也不知道您分配的作为起点的内存(在矩阵的一行中(指向该行。

其次,您必须明确地告诉编译器您想要发生什么,而不是依赖编译器来猜测,这也可能导致未定义的行为。

我将使用 8 位地址来说明这一点。

ptr = (char**)malloc(sizeof(char*) * 3),它可以在0x30 0x31 0x32分配地址,每个地址将存储一个8位类型。假设你做*(ptr + 0) = malloc(4).malloc 调用将返回一个指针,指向可以存储字符的四个连续位置。假设它返回0x40这意味着地址0x40 0x41 0x42 0x43都可以使用。

但是,地址0x30处的值是0x40分配的,现在请记住,指针不是一种类型,而是数字的二进制表示形式,恰好表示一个地址。因此,指针没有释放器(例如C++中的析构函数(的奢侈。编译器不知道此值用于访问分配的内存地址,而是为您存储该值。因此,呼叫free(ptr)只会释放0x30 0x31 0x32的地址。

简单地说,假设您将四个整数作为1 2 3 4存储在int*中,如果编译器试图释放四个整数作为地址,则会遇到问题,因为您实际上是在告诉编译器free地址0x01 0x02 0x03 0x4这些地址在旧系统上会产生可怕的后果,而在现代系统上, 您的应用程序将被终止。

这最初可能看起来很不方便,但是,这意味着使用这些指针具有一定的灵活性。例如,您可能希望再次使用ptr,而不是调用free和调用malloc来指向另一个矩阵。

如果释放矩阵的所有行也释放了指向行的指针,则可能会遇到分段错误的情况,因为您不知道指向此地址的指针。

在这样说时,您有责任跟踪这一点,并确保堆不会累积没有指向它的引用的数据。

您应该始终执行与 mallocs 完全相同数量的释放。

您可以将代码重写为:

char **ptr;
ptr = malloc(sizeof(char*) * 3); //A
*(ptr + 0) = malloc(4); //B
*(ptr + 1) = malloc(4); //B
*(ptr + 2) = 0; //C

你 malloc 3 次:

  • 一个。你 malloc 一个数组来保存 3 个指向 char 数组的指针。
  • 二.您错误地放置一个包含 4 个字符的数组,并将其分配给您在 A 中创建的指针值之一。
  • 三.将 A. 的最后一个元素设置为0。这与将其设置为NULL相同。但是,大卫指出,将其设置为NULL更好。这是一个特殊值,称为空指针。

首先释放ptr是行不通的,因为您随后会丢失*(ptr+0)等的值。因此,您必须首先释放*(ptr+0),并在您错误定位它们时*(ptr+1)。但是你不必释放*(ptr+2),因为你没有恶意移动它。

<块引用类>

但是,您可以安全地调用 free on*(ptr+2),就像您之前将其设置为NULL一样,并且您始终可以安全地释放 null。为了安全起见,我总是在释放后设置一个指向NULL的指针。

*(ptr + 0)*(ptr + 1)只是指向您使用(char*)malloc(4);分配的内容的指针。释放ptr将释放这些指针本身,而不是它们指向的内存。Free 不是递归的。因此,必须先释放单个指针,然后才能释放指针数组。

相关内容

  • 没有找到相关文章

最新更新