【问题标题】:Why does GCC allocate stack space that it does not use?为什么 GCC 分配它不使用的堆栈空间?
【发布时间】:2016-03-05 20:39:00
【问题描述】:

在许多函数中,函数序言以sub $0x1c,%esp 开头,后来被add $0x1c,%esp 删除。该功能可以简单到几乎什么都不做。然而,这个空间从未被使用过,并且已经成为一种烦恼,因为我需要完全控制我的函数堆栈。知道是什么原因造成的,我该如何删除它?我正在使用-O2 -Wall -c -m32 -fno-stack-protector -fno-defer-pop -fno-builtin -march=i386 进行编译。

【问题讨论】:

  • “我需要完全控制我的函数堆栈” - 好奇:为什么?这正是编译器的用途。
  • 一些 ABI 要求调用堆栈上有一些红色区域。您的 ABI 和操作系统是什么?
  • 还有对齐的问题。
  • @OliverCharlesworth 我正在编写一个系统调用机制,并在调度之前控制哪些返回地址保留在堆栈中。然后当我尝试返回一个地址时它会变得很麻烦,但是堆栈已被 GCC 修改,我需要在到达“add $0x1c,%esp”之前返回。
  • @Seralize:您不能假设编译器不会更改堆栈指针或修改任何寄存器。如果你需要这样做,你必须在 asm 中编写整个函数,而不是像 inline asm 那样。

标签: c gcc x86


【解决方案1】:

查看更多代码会有所帮助,但这与堆栈对齐有关。你可以在 GCC 中使用 -mpreferred-stack-boundary 来解决这个问题。我机器上的默认值是 4,所以东西对齐到 16 个字节。我非常有信心这与堆栈保护无关。要查看堆栈保护会发生什么,请使用 -fno-stack-check 和 -fstack-check 编译程序并比较结果。你会看到类似

>   orl $0, -12300(%esp)

【讨论】:

  • 保持堆栈对齐仅说明小于 0x10 的调整,然后仅适用于非叶函数。
  • @PeterCordes 我不确定我是否同意。高速缓存行是强制以 32/64 或 128 字节对齐的原因之一。堆栈指针的减法包括本地所需的任何必要的堆栈空间等,包括编译器认为必要的任何填充。在不了解更多关于 OP 使用的平台和一些代码的情况下,很难说出真正发生了什么,但我坚持对齐作为原因。注意,这里有一个关于 Clang 的错误,讨论 gcc 4.8 上的 32 字节堆栈对齐...llvm.org/bugs/show_bug.cgi?id=18006 32 字节字节对齐并非闻所未闻。
  • 是的,我想知道 OP 是否正在查看一个确实使用了它保留的 一些 空间的函数,但我想我会从字面上理解他的主张并假设他在一个不使用堆栈的函数中看到sub esp, 0x1c,除了加载参数并返回一些东西。我认为我们都同意我们需要来自 OP 的更多信息才能说出任何有用的信息。不过,16B 对齐是您通常会看到的最大对齐,因为 AVX 需要对未对齐内存的有效支持。因此,与非 VEX SSE 不同,如果使用未对齐的加载/存储完成,溢出 ymm regs 不会受到太大影响或需要额外的 movs。
  • Why does GCC allocate more space than necessary on the stack? 演示了 GCC 过度分配了它不需要对齐的堆栈空间。
猜你喜欢
  • 2023-03-29
  • 2020-11-10
  • 1970-01-01
  • 2013-03-26
  • 2012-04-09
  • 1970-01-01
  • 2012-12-26
  • 2021-07-17
相关资源
最近更新 更多