【发布时间】:2021-01-02 14:11:01
【问题描述】:
我有以下 C 代码,在这里我不太明白malloc 的行为:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
size_t* v3;
char *message;
size_t size;
v3 = malloc(10uLL);
*v3 = 1LL;
printf("first address: %p\n", (void *)v3);
size = 0;
scanf("%lu", &size);
message = malloc(size);
read(0, message, size);
message[size-1] = 0;
write(1, message, size);
if(!*v3) printf("you win");
else printf("you didn't win");
return 0;
}
所以程序分配了一些内存,然后我们打印地址。现在,如果我使用这个地址作为一个数字并将其加 1,然后将其作为下一个malloc 的大小提供,那么当message[size-1] = 0 发生时,它基本上会溢出并修改v3。它被设置为1LL,但之后它是0,并且打印了“you win”。
谁能解释一下这是怎么回事?
正如 cmets 中所建议的,这是我运行程序时发生的情况:
第一个输出是:first address: 0x5581cb0646b0
然后我只打开一个 python shell 并执行:int("0x5581cb0646b0", 16) + 1 将十六进制值转换为数字并将1 添加到它,得到94015945328305
我将此提供给scanf,然后read 运行,但此处的消息可以是任何内容,不会改变发生的情况。
最后,打印出消息,然后是“you win”。 (但请注意 *v3 应该是 1LL 而不是 0。
【问题讨论】:
-
我建议
(void *)&v3应该是(void *)v3。我看不出“将地址作为数字并将其加 1,然后将其作为大小提供”有任何意义。 -
message[size-1] = 0 happens it basically overflows and modifies v3您是否期望 malloc 的返回值是连续的?这是一个理论上的例子吗?你真的执行了这个程序吗?how this happens?请发布程序执行的输出。 -
我的猜测是
scanf失败,所以size仍然为零,然后message[size-1] = 0损坏内存,因为索引超出范围。 -
这是一个足够短的程序,您应该能够逐行调试它,看看谁在更改
*v3。 -
malloc不会不覆盖以前的分配:问题出在这个非常奇怪的代码中,它不检查任何内容,也不报告“之前”和“之后”。
标签: c memory memory-management heap-memory