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



代码片段,在底部,我试图导致以下错误

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;
}

EDIT我问这个问题的目的是知道/理解当程序运行时堆内存中的记账信息发生了什么。如果能提供一些数据结构被修改的信息,那就太好了。或者我想从设计的角度了解。

感谢大家的捐助。

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

在这种情况下,程序已经损坏了堆。

memset的签名:

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

对于malloc,您分配10字节的内存,并将指向该内存的指针分配给check。(不是一个解决方案,但你不应该强制转换malloc的返回值)

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

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

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

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

这个的具体细节(什么被破坏了,它如何影响free)是非常非常非常依赖于实现的。在这方面,不同的实现可能有很大的不同。如果不知道您正在使用的具体实现是什么,就无法提供更具体的描述。

在现代操作系统中,分配的内存从内核空间中分成非常大的块来管理,然后由用户空间代码分配成更小的块。

用户空间代码通常通过使用双重链表以及每个分配块前后的哨兵数据来跟踪已分配和空闲的内存。哨兵数据包括幻数、块大小等。

哨兵数据帮助内存管理器检测用户程序何时写入超过(或之前)分配的大小。双重链表的使用有助于内存管理器将释放的小块组合成更大的已释放段,以帮助避免碎片。

当写入超出分配的大小时,不仅会破坏哨兵数据,还可能会破坏链表数据。一旦链表被销毁,大多数内存管理器就会崩溃,因此关于保留之外的内容的注释也会崩溃。

最新更新