一个简单的 C 程序,但是不明白区别在哪里

143 天前
 kelvinaltajiin
#include <stdio.h>
void assign_value(int *array, int index, int value);
int main() {
  printf("Hello, World!\n");
  int array[10];
  assign_value(array, 16, 131);
  printf("%d\n", array[16]);
  return 0;
}

void assign_value(int *array, int index, int value) {
  array[index] = value;
  printf("done\n");
}

编译:$ gcc -g -Wall -std=c18 -o hello_world hello_world.c 运行输出:

Hello, World!
done
131
[1]    3719 segmentation fault (core dumped)  ./hello_world

但是如果把 index 从 16 改成 12, 则不会出现最后的 segmentation fault. 如果 C 不处理越界的话,为什么 16 会报错,如果处理越界为什么 12 不报错?

4500 次点击
所在节点    C
32 条回复
jettming
143 天前
内存默认 32 位对齐,和经典的 struct {char a; int b;} s;分配了 8 字节类似。难得在这看到有人用 C 语言的,哈哈。
kelvinaltajiin
143 天前
@w568w #16 看来得回炉重新看看汇编了😂 “未定义行为”解释的很清楚,感谢,有点法无禁止即可为的意思了
kelvinaltajiin
143 天前
@xpzouying #18 我咋忘了 AI 呢😅
kaedeair
143 天前
因为在回收资源的时候系统发现你把这一块内存写坏了,内存是有上下文的,边界被破坏了,所以才报错。你可以试试把偏移量换成一个比较大的数字,可能还没到返回的地方就报错了。至于小一点没报错是因为这一块内存没有被使用,是合法地址。
csfreshman
143 天前
数组访问越界,会导致未定义行为,后面的行为表现千人千面,每个人机器运行出来有可能都不一样。
csfreshman
143 天前
@xpzouying info trace 这个依赖 gcc 版本吗?为啥我编译选项加了-fno-omit-frame-pointer ,还是看不到栈帧信息。
fr13ncl5
143 天前
从漏洞利用的方面,一个 12 估计只写到了不重要的栈内容,但是 16 可能就写到了函数栈帧的返回地址,返回到了错误地址,然后触发 SEGSEV 。但是这是 Linux ,如果换了 windows ,编译器或者任何系统设置的不同都有可能让 16 那个位置的内存含义不同,这就变成了未定义的事了
hefish
143 天前
可以用 gcc -S 编译成汇编代码,然后对照着看一下。
restkhz
143 天前
我用这个代码在本地用 gcc 编译了一下,但是没有复现出你的情况。
用了 gdb 和 cutter 。调试看到,16 这个位置已经写到栈顶环境里面了。

也就是说,写到了 main 栈之上的东西。

我这没有复现的原因是貌似是因为写入了一个没啥用的指针地址。应该是连接器搞的,指针跳了几下跳到.comment 段,应该是一直都没有用到。
但是在他隔壁 15 就是一个指向 libc 的指针。覆盖这里就覆盖了那个指向 libc 的地址,而后会和你出一样的问题。
也就是赋值 ok, printf 也 ok ,就是在退出时崩溃。在程序结束时 segmentation fault(core dumped)。查了一下,这个貌似是用于 main 退出时会调用的。
另外覆盖 14 也是一个重要地址。但是我这里 16,17 都不重要。

我比较菜,这里的东西我也不那么熟悉就是。但是我怀疑你遇到的是这个情况。
kelvinaltajiin
142 天前
@hefish #28 汇编的知识已经还给老师很久了
kelvinaltajiin
142 天前
@restkhz #29 根据楼上的回复,溢出导致未定义行为,不同机器不同环境结果都不确定,我对 C 的标准也不太熟悉,遇到这些问题容易懵
PTLin
142 天前
你这 Linux 上的情况严格来说是因为访问的地址 array[16]碰巧超过了作为栈的页边界,引发了缺页中断,然后中断处理函数里发现你访问的地址没有建立起页面映射,然后引发的段错误。
不能保证不同编译器编译后的程序都能准确地引发段错误。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1125556

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX