我为堆溢出写了一个简单的程序(提供比所分配的内存更大的输入),当我试图打印该输入时,我得到了完整的字符串(因为在内存中遇到'/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,我的系统即使在巨大的输入下也非常稳定。
你们谁能解释一下崩溃的具体原因?
该 确切 崩溃的原因是GLIBC内部的堆实现能够检测到堆损坏。此番,并称为 abort()
.
就像其他人说的那样,你在行使未定义的行为,所以... 任何 可能发生。
在不同的系统上,或使用不同版本的GLIBC,或对不同的用户,或设置不同的环境变量时,这种崩溃可能不再发生(这就是 无病呻吟).
我觉得这种未定义的行为只是 "未定义的行为",也就是说我们没有花功夫去分析系统的行为。
它是 无意义 来分析系统行为:你在玩俄罗斯轮盘赌。你可能会很幸运,在你的特定环境中,枪要么是完全空的,要么是完全满的,所以你会得到可预测的行为。但你不能让 任何 由此得出的结论 -- -- 在不同的系统上,或者明天,系统可能会有不同的表现。