【问题标题】:Label moving after optimization is turned on in gcc在 gcc 中打开优化后的标签移动
【发布时间】:2011-05-25 16:14:33
【问题描述】:

在 gcc 中开启 1 级优化后,我遇到了一个奇怪的问题。我所做的是保存标签并稍后从不同的函数返回到它。

void
UMS__suspend_procr( VirtProcr *animatingPr )
{ 
   animatingPr->nextInstrPt = &&ResumePt;


   [Some Code and inline volatile asm]

   ResumePt:
   return;

}

我做了一些这样的跳跃,它们都工作得很好。 问题是当我打开 O1 时,它没有保存正确的标签地址。相反,它会这样做:

804b14e:       8b 45 08                mov    0x8(%ebp),%eax
804b151:       c7 40 14 4e b1 04 08    movl   $0x804b14e,0x14(%eax)
804b158:       8b 55 08                mov    0x8(%ebp),%edx

所以程序甚至在分配之前就跳回来了。

【问题讨论】:

  • 您知道获取标签地址是一种非标准语言扩展吗?因此完全不便携。

标签: c optimization gcc x86 label


【解决方案1】:

此代码不是有效的 GNU C。首先,计算的 gotos (&&label) 是 GNU C 特有的功能,不是 C 语言的一部分,但如果您使用的是 GNU C,那没关系。但是,它们在 GNU C 中唯一有效的地方是 goto 语句。您不能将带有 inline asm 的指针用作间接跳转/调用目标,因为调整堆栈帧取决于编译器,并且从 inline asm 点和标签目标点的堆栈帧的当前逻辑视图可能不匹配.使用显式的 goto 语句,编译器可以修补它,但使用 asm 甚至无法判断它正在发生。

至于大局,如果您正在编写这样的代码,您真的应该重新考虑您的一些假设。当然有更好的方法来完成你想要的。

【讨论】:

  • 是的,我知道这只是 GNU C 的一部分。堆栈很好,我总是跳回相同的函数,每次我 jmp 时都会保存堆栈帧并使所有寄存器无效。这可能是移动标签的原因吗?
  • 栈不好。编译器可以随时随地随意调整,这不在您的控制范围内。根本不允许你做任何你想做的事情。如果它“有效”,那纯属运气,它可以而且将会坏掉。
  • @merten:不管堆栈如何,您都会说“我所做的是保存标签并稍后从不同的函数中跳转回它。” ——好吧,GCC 文档非常明确地指出:“你不能使用这种机制来跳转到不同函数中的代码。如果你这样做,将会发生完全不可预测的事情。” (参见recent version here;完全相同的语言已经存在了很长时间。)
猜你喜欢
  • 1970-01-01
  • 2017-02-15
  • 1970-01-01
  • 2023-03-30
  • 1970-01-01
  • 1970-01-01
  • 2010-10-30
  • 1970-01-01
  • 2021-03-10
相关资源
最近更新 更多