18 条回复  ·  2137 次点击
kelvinaltajiin 楼主 小成 2025-4-15 12:08:02
@ho121 @codehz @geelaw @gnahzraensim @kirory @zeromake 感谢各位,应该就是内存对齐的原因,12 可能刚好还保持在取回来的内存块,16 可能就到了下一个内存块了
balckcloud37 初学 2025-4-15 12:09:24
编译器决定了开的栈的大小,越界访问如果没超过栈,可能只是改了后面的某个 local var ,如果超过以至于访问了 invalid memory 就会 segfault ,但你不知道编译器开了多大的栈、也不知道变量的布局,所以哪种情况都有可能,所以才是 undefined behavior
codehz 初学 2025-4-15 12:09:52
@kelvinaltajiin c 编译器只需要保证“标准里已经定义过”的行为是确定的就好,这里的行为是指纯外部效果和标准里描述的是一致的,至于没定义的部分,就是自由发挥 这个概念下,你声明一个数组,编译器真的会给你安排一个数组的空间吗,这也未必,只要最后运行结果,“看起来和有一个数组”一样就可以了,虽然目前的编译器还没有做这样激进的 preeval 的优化,但这在理论上是一种方案,但就算是目前不太激进的方案,也会在很多地方影响编译器分支选择上的决策,例如直接跳过可能触发未定义行为的路径
Shatyuka 初学 2025-4-15 12:42:32
@codehz “虽然目前的编译器还没有做这样激进的 preeval 的优化” 有的,他这个代码开 O1 优化,数组就没了。gcc 、clang 、msvc 都是。 “例如直接跳过可能触发未定义行为的路径” clang 检查出了数组访问越界,O1 优化下不会 printf 131 ,是个未初始化的值。
kelvinaltajiin 楼主 小成 2025-4-15 12:42:57
@balckcloud37 #11 @codehz 感谢两位,解释得很清晰,很符合 v 站的风格,让自己的发言对别人有帮助,再次感谢
celeron533 初学 2025-4-15 13:23:30
眼前一亮:缓冲区溢出攻击 :P
w568w 小成 2025-4-15 13:39:01
先回答问题。看汇编就很明显了: https://godbolt.org/z/1e65616jo 就像楼上说的,在 GCC 的实现下,(rbp-48) ~ (rbp-8) 是数组占据的空间,但你访问 (rbp-4) 和 rbp 位置都不会有问题(即 array+10 到 array+12 )。再往下访问就越界了。 然后关于未定义行为。学究一点地说,未定义行为的意思就是「编译器想怎么做都可以,怎么方便怎么来」。 如果编译器觉得输出格式化和病毒代码很方便,那它就可以在你写未定义行为的地方输出这些代码。不要惊讶,标准明确告诉你「未定义行为无论发生什么都行」,这是完全合法的,无法从规范上指责它。 总结就是,不要尝试和利用未定义行为。这就是 C 的遗留问题,如果你觉得不能接受,换一门更近代的语言吧(比如 Java 、Go )。
mahaoqu 小成 2025-4-15 13:45:19
加上 -fsanitize=address 就好了,一定会报错
xpzouying 初学 2025-4-15 13:52:39
点击链接查看和 Kimi 的对话 https://kimi.ai/share/cvuv86n6o68nvril4hcg 直接 kimi 解决
12
返回顶部