为什么在堆溢出后调用free()会导致崩溃 - 具体原因是什么?

问题描述 投票:-1回答:1

我为堆溢出写了一个简单的程序(提供比所分配的内存更大的输入),当我试图打印该输入时,我得到了完整的字符串(因为在内存中遇到'/0'之前都会进行检索),直到这一部分都很清楚。

但是当我调用 free()系统崩溃,并得到一些错误信息,如以下所示

free() invalid next size (fast) aborted (core dumped): some_address

这里的地址指向通过 malloc.

以下是我的代码

#include <stdio.h>
#include <stdlib.h>
int main()
{
    char *string = (char*)malloc(sizeof(char)*10);
    scanf("%s", string);     //intentionally i am providing input much longer than 10 bytes
    printf("\n string input given by user is %s\n", string);
    free(string);

    return 0;
}

在我想知道这次崩溃的确切原因的路上,我知道了实时和免费的chunks都包含哪些元数据,以及GLIBC管理的 "bins "的一点情况。

我知道了,一个活的chunk存储的元数据是:size(指定我请求了多少,它将被对齐为8或16),还有一些关于竞技场、前一个chunk、off-heap的位子,最后会有指向前一个chunk的指针(如果前一个chunk是空闲的)。

起初我以为前一个chunk可能是空的,当GLIBC试图获取前一个chunk的地址并与我传给free()的chunk合并时,因为我做了溢出,所以在前一个chunk指针字段中遇到了一些垃圾值,但后来当我看到了 free() 函数的定义和错误信息,更清楚的是,我知道它与 快餐盒,而快速仓不会将chunk与之前的chunk合并,所以我的假设是错误的。

你们有谁能解释一下崩溃的具体原因吗?我试着读了一下代码,然后迷失了方向,因为当他们在做 "chunk_at_offset "的时候,有一些时间点

从代码和一些图形化的表达方式来解释将非常有帮助。

这个 是我所提到的源代码的链接。

edit:我使用的是onlinegdb c编译器,我在我个人的机器上也试过,我的机器上有Ubuntu GLIBC 2.27-3ubuntu1,我的系统即使在巨大的输入下也非常稳定。

c memory free glibc
1个回答
0
投票

你们谁能解释一下崩溃的具体原因?

确切 崩溃的原因是GLIBC内部的堆实现能够检测到堆损坏。此番,并称为 abort().

就像其他人说的那样,你在行使未定义的行为,所以... 任何 可能发生。

在不同的系统上,或使用不同版本的GLIBC,或对不同的用户,或设置不同的环境变量时,这种崩溃可能不再发生(这就是 无病呻吟).

我觉得这种未定义的行为只是 "未定义的行为",也就是说我们没有花功夫去分析系统的行为。

它是 无意义 来分析系统行为:你在玩俄罗斯轮盘赌。你可能会很幸运,在你的特定环境中,枪要么是完全空的,要么是完全满的,所以你会得到可预测的行为。但你不能让 任何 由此得出的结论 -- -- 在不同的系统上,或者明天,系统可能会有不同的表现。

© www.soinside.com 2019 - 2024. All rights reserved.