为什么这个指针无效?

时间:2011-11-09 00:21:48

标签: c

char* x = malloc(512);
memset(x, 0, 513);
free(x);

为什么这会导致程序崩溃?这是在说free(): invalid pointer: 0x0000000000614010 这没有任何意义,如果它应该破坏程序的其他随机部分,因为它写入未定义的内存空间。

5 个答案:

答案 0 :(得分:14)

您已导致未定义的行为,因此任何都可能发生。在这种情况下,您的free()实现可能会在缓冲区后立即检查空间中的某些信息。既然你把它覆盖了,它的游戏结束了。

答案 1 :(得分:3)

我是新人,但我希望我能满意地回答这个问题。

您通过覆盖已分配块的重要部分来激发未定义的行为。您正在删除由malloc写入的该块上的大小信息的第一个(高位字节)。大多数C标准库使用附加的Doug Lea Malloc并在块上添加一些字节,其中包含大小和使用信息。通过覆盖它,您实际上会破坏free()调用成功所需的信息并真正释放malloc内存。 malloc的某些实现不会这样做并保留一个“带外”表(在其他地方你不会覆盖它)用于块对齐和大小,有些只是预先添加/附加该信息。正如我所说,你的程序崩溃了,因为你覆盖了重要信息,而free()无法完成它应该做的事情。

答案 2 :(得分:2)

malloc 512个字节,并且你用memset 513个字节写,所以你已经破坏了堆。

如果它还不是很明显,那就是未定义的行为。你崩溃了,因为你溢出了堆并写了一个用于管理堆结构的重要地址。

答案 3 :(得分:0)

您已经分配了512个字节的内存,但是正在写入513个字节。 free()可能会检查内存区域是否仍然有效(如果它包含您已写入的保护字节,则不会是。)

答案 4 :(得分:0)

堆分配器通常在分配内存之前和/或之后立即放置一些簿记信息。你观察到的一个可能的解释是你已经覆盖了一些对内存分配器操作至关重要的数据,可能是分配的块的大小或下一个空闲空间的位置。

在任何情况下,在已分配空间的边界外写入都是未定义的行为,任何事情都可能发生。仅仅因为现在发生的事情并不意味着它将在不同的系统上发生,甚至在不同的时间在同一系统上发生。相反,即使您没有看到错误,也不意味着不会调用未定义的行为。这是使用诸如C的不安全语言的成本。