c - 为什么 -fno-stack-protector 会颠倒这些字符串的存储顺序?
问题描述
我有以下功能:
void f(){
char a[]="THIS IS A STR 1";
char b[]="THIS IS A STR 2";
char c[]="THIS IS A STR 3";
char d[]="THIS IS A STR 4";
}
当我正常编译和运行这个程序时,这些字符串是这样分配在堆栈上的:
08 00 00 00 04 00 00 00 10 00 00 00 10 00 00 00 ................
10 71 c7 64 fc 7f 00 00 07 a9 90 7b 24 56 00 00 .q.d.......{$V..
54 48 49 53 20 49 53 20 41 20 53 54 52 20 31 00 THIS IS A STR 1.
54 48 49 53 20 49 53 20 41 20 53 54 52 20 32 00 THIS IS A STR 2.
54 48 49 53 20 49 53 20 41 20 53 54 52 20 33 00 THIS IS A STR 3.
54 48 49 53 20 49 53 20 41 20 53 54 52 20 34 00 THIS IS A STR 4.
a0 69 d9 76 c8 7f 00 00 00 dc ad e1 c7 89 e9 11 .i.v............
30 71 c7 64 fc 7f 00 00 37 a9 90 7b 24 56 00 00 0q.d....7..{$V..``
堆栈向更小的内存地址增长(在本例中为“向上”),因此这些字符串的存储顺序对我来说似乎是相反的。
而当我使用 -fno-stack-protector 编译和运行时,我得到了“正确”的顺序。
00 00 00 2e 10 00 00 00 08 00 00 00 05 00 00 00 ................
80 20 05 0f ff 7f 00 00 88 58 bb 32 96 55 00 00 . .......X.2.U..
54 48 49 53 20 49 53 20 41 20 53 54 52 20 34 00 THIS IS A STR 4.
54 48 49 53 20 49 53 20 41 20 53 54 52 20 33 00 THIS IS A STR 3.
54 48 49 53 20 49 53 20 41 20 53 54 52 20 32 00 THIS IS A STR 2.
54 48 49 53 20 49 53 20 41 20 53 54 52 20 31 00 THIS IS A STR 1.
a0 20 05 0f ff 7f 00 00 a4 58 bb 32 96 55 00 00 . .......X.2.U..
88 21 05 0f ff 7f 00 00 00 00 00 00 02 00 00 00 .!..............
我的印象是堆栈保护器所做的所有事情都放在堆栈金丝雀中,那么为什么它会像这样重新排列内存分配方式呢?
解决方案
当您有嵌套的函数或块时,堆栈“增长”的顺序是指不同堆栈帧的位置。它也将朝这个方向增长,需要在堆栈上动态分配临时对象。
然而,变量在栈帧中的位置是完全任意的;没有什么要求它与变量声明的顺序相同。编译器可能会在堆栈帧中重新排序变量的原因有很多。例如,具有较小对齐要求的变量可能会一起移动,以最小化填充。
这些字符串在您使用时被反转的事实-fno-stack-protector
可能只是通过优化器的不同代码路径的副作用。我怀疑是否有任何具体原因,但这不重要。
推荐阅读
- javascript - Bootstrap Datetimepicker 在第二次点击时消失
- docker - Kafka-Node 未检测到 kafka 代理
- debugging - 如何在 Erlang 中调试进程
- clang-tidy - clang-tidy:在 throw 之前由于缺少 free 而检测内存泄漏的检查是什么?
- rest - 使用不透明的访问令牌会使我的服务器有状态吗?
- c# - 在 ASP.NET MVC 中没有为此对象定义无参数构造函数
- python - 为什么它一直说“在处理上述异常期间,发生了另一个异常:”
- java - JDK 11.0.2 - 无法在 ECLIPSE 中派生模块描述符
- c - 尽管初始化变量,但它正在获取垃圾值
- android - 如何使用导航组件处理片段内的向上按钮