c - 为什么我的 char[30] 堆栈增加到 0x38

标签 c assembly x86

在这个方法中

void lame(void) {
 char small[30];
 gets(small);
 printf("%s\n",small);
}

我希望堆栈增加 0x20

但是 gdb 显示它增加了 0x38

0x08048450 <+3>:  sub $0x38, %esp

我不太确定回答这个问题需要什么信息,所以如果我遗漏了什么,请告诉我,我会添加:

  • Ubuntu 140.04 32 位
  • 编译命令:cc -ggdb -fno-stack-protector blah.c -o blah
  • CC --version - 4.8.2
  • 在 Oracle Virtual Box 4.3.20 中运行

我在做什么 只是想解决缓冲区溢出问题,发现 this我正在关注的例子

disas lame

disas lame output

最佳答案

对于初学者来说,您的缓冲区向上舍入为 0x20 字节,这不足为奇。传出参数需要 4 个字节。所以我们有 0x24 字节的净要求。

更新后的调用约定要求堆栈指针必须保持 16 字节对齐。由于 push %ebx 使用 4 个字节,另外 4 个字节用于 call 指令放入堆栈的返回地址,因此调整必须从 8 个字节开始16 的倍数。这与我们对 0x24 字节的最低要求相结合意味着分配 0x28 应该足够了。 gcc 而不是为总共 0x38 分配 16 个额外字节似乎是至少 gcc 版本 4.4 到 4.9 表现出的错误或特性。请注意,clangllvm-gcc 都分配了预期的 0x28 字节。

我的测试排除了与使用 gets 或编译器将 2 个参数 printf 优化为 1 个参数 puts 有关的额外空间.

关于c - 为什么我的 char[30] 堆栈增加到 0x38,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27913570/

相关文章:

c - 如何在C中丢弃一行的其余部分

c++ - 汇编代码中的静态值

debugging - 如何在OllyDbg中搜索特定CPU指令?

linux - 为什么派二进制文件不允许使用 "symbol@GOT"?

c - C 结构体中的类型

c++ - Fortran 中 REAL(KIND=real_normal) 的 C 等效类型是什么?

c - 如何将字符串拆分为字符串数组?

c++ - 获取 `rsqrtss` 包装器的最少指令

c - 正则表达式如何翻译成汇编?

assembly - x86 Intel 汇编器 LEA