【问题标题】:can GOTO create an overflow in stack memory? StackOverflow?GOTO 可以在堆栈内存中创建溢出吗?堆栈溢出?
【发布时间】:2019-12-13 22:19:39
【问题描述】:

我不是 C 方面的专家,但我做得很好,我的主要是嵌入式系统和微控制器编程。

我知道避免使用 GOTO 指令是一种误解,因为它会创建意大利面条式代码。 作为一名微控制器程序员,我经常将汇编语言用于小程序,而 GOTO 是唯一的方法,但就像在 C 中一样(或者不像可能?)在使用指令时必须小心,因为如果你在一个子程序中例如,您可能在堆栈内存中使用了一个空间,因此您可以返回到原始例程。

但是,如果您错误地使用 GOTO 指令从您的子程序跳转到主代码,那么您并没有释放堆栈内存,并且如果您多次调用子程序最终会溢出。

所以我的问题是,当我们在 C 中编写一个嵌套循环时,例如一堆 FOR,并且我们使用 goto 指令从内部循环中中断,这会导致与我之前描述的相同的问题吗?

【问题讨论】:

  • 这是不可能的。
  • 问题应该集中在GOTO in C,它不能跳转函数(因此不能改变堆栈或导致堆栈溢出本身) ;或者;专注于可以的'等效'低级汇编指令。考虑适当地更新标签。
  • 实现相同的另一种可能性:stackoverflow.com/questions/23823277/…
  • 不行,C的goto关键字只能跳转到同一个函数范围内的标签。自己尝试一下,看看编译器会告诉你什么。
  • 我怀疑很多“仇恨”可以追溯到其他控制结构相对较新的时候,但程序员不愿意采用它们(就像说服程序员可以使用高级语言一样需要一段时间用于系统编程而不是组装)。所以语言过于苛刻,因为当for 和/或while 更合适时使用goto。现在它被谨慎使用,当其他构造不适合时,没关系。

标签: c assembly stack-overflow microcontroller goto


【解决方案1】:

goto不能用于函数间跳转,只能在同一个函数内跳转。所以它不会添加到堆栈中,也不会允许堆栈帧丢失。

允许直接跳转到另一个函数的更受约束的机制是setjmp()longjmp()。但是longjmp() 只能在调用setjmp() 的函数的生命周期内使用相同的jmp_buf,并且指定将堆栈展开到该函数(语言规范实际上并不指堆栈,而是使用更通用的语言,但在大多数实际实现中都相同)。

【讨论】:

  • 请注意,longjmp 不执行 C++ 样式的堆栈展开;它跳过它传递的任何作用域的析构函数。它实际上只是一个上下文切换回setjmp 调用点(恢复调用保留寄存器,包括堆栈指针),返回另一个返回值。
  • @PeterCordes 我懒得提这个问题,因为这个问题被标记为 C。
  • 哦,是的,堆栈展开的另一部分(恢复调用保留的寄存器)由seg/longjmp 的状态保存/恢复覆盖,所以根本没有明显的区别和我的评论毫无意义。我开始编写它是因为 Linux 上使用的 System V ABI 确实指定了 .eh_frame 元数据以进行堆栈展开,即使在编译 C 时也是如此,而且它是非可选的,因此即使 strip 也不应该删除它。并且因为您使用了“堆栈展开”这个短语;这通常意味着一次一帧;我可能会在这里使用不同的短语,例如将堆栈“重置”到此上下文。
猜你喜欢
  • 2019-05-18
  • 2012-03-24
  • 1970-01-01
  • 1970-01-01
  • 2012-04-15
  • 2012-12-20
  • 2011-03-02
  • 2011-08-22
相关资源
最近更新 更多