为什么malloc()之后的无效memset()导致free():下一个大小无效(快)

时间:2014-05-14 00:12:06

标签: c memory free memcpy memset

底部的代码段,我正在尝试导致以下错误

free(): invalid next size (fast)

以上错误,是由于在指针 检查 意外调用memset()后声明整数变量 mock 引起的>大小超过最初使用malloc()分配的大小。当在指针 检查 上调用free()时,会导致运行时错误。

如果有人能够解释内部存储器的操作方式或实际发生错误的原因,那将会很有帮助。

提前致谢。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    char *check = (char *)malloc(sizeof(char) * 10);

    memset(check, 0, 100);

    memcpy(check, "memsetcpy", 10);

    int mock = 9;

    free(check);

    return 1;
}

编辑我提出问题的意图是了解/了解程序运行时堆内存中的簿记信息会发生什么。并且可能有一些关于被修改的数据结构的信息会很棒。 或者我想从设计的角度来了解。

谢谢大家的抨击。

4 个答案:

答案 0 :(得分:4)

当程序在定义的内存空间外写入时, 任何 都可能发生。

在这种情况下,该程序已损坏heap

答案 1 :(得分:3)

这是memset

的签名
void * memset ( void * ptr, int value, size_t num );

使用malloc,您可以分配10个字节的内存,并将指向该内存的指针分配给check。 (不是解决方案,但是你should not cast the return value of malloc

然后使用memset,将100个字节的零写入check指向的内存块。

您的程序正确写入前十个字节,然后将分配的空间后的90中的任何内容清零。由于你在分配的内存之外写作,任何事情都可能发生,在这种情况下,我猜你在内存上写了包含malloc / {{1的簿记信息的内存内存分配系统。当然,既然你正在调用未定义的行为,那么它也可以让你的计算机长腿并走开。

答案 2 :(得分:1)

典型的动态内存(堆)实现在那里存储大量家庭信息,在同一存储器中与用户数据交织。您分配的每个内存块通常包括一个特殊的标题区域,可能还包括一个特殊的页脚区域。这些区域从两端围绕您的用户区域。您只能操纵用户区域内的内存。但是,当您在该用户区域的边界之外编写任何内容时,您肯定会损坏这些内部页眉和页脚区域。这完全破坏了动态内存管理子系统的完整性。其余部分如下。

在您的情况下,您将超出用户区域90个字节。这很多。您可能销毁了许多对动态内存正常运行至关重要的内部家庭数据。

具体细节(受损以及后来如何影响free)非常非常非常依赖于实现。在这方面,不同的实现可以大不相同。如果没有至少知道您正在使用的具体实现,就无法提供更具体的描述。

答案 3 :(得分:0)

在现代操作系统中,分配的内存在内核空间的非常大的块中进行管理,然后通过用户空间代码以较小的块分配。

用户空间代码通常通过在每个分配的块之前和之后使用双向链表以及标记数据来跟踪分配的和空闲的存储器。标记数据包括幻数,块大小等。

标记数据有助于内存管理器检测用户程序何时写入其分配的大小(或之前)。使用双向链表有助于内存管理器将释放的较小块组合成较大的自由段,以帮助避免碎片。

当您编写超出分配的大小时,您不仅会破坏标记数据,还可能破坏链接列表数据。一旦链表被破坏,大多数内存管理器就会分崩离析,因此关于事情的评论会从预订中消失。

希望这有帮助。