C语言 是否可以在调用va_end之前进行longjmp



在本Q&A中,您应该始终调用va_end():

va_end到底是干什么用的?总是需要调用它吗?

但是如果一段代码在到达va_end之前长了jmp's呢?va_end方面是否有任何承诺,它将是好的?或者从概念上讲,它(例如)va_start()中做内存分配,这将被泄露,而不是仅仅使用堆栈技巧?

C99的基本原理明确指出,va_start可能分配内存,最终由va_end释放,正是你在你的问题中猜测的:

7.15.1.2 va_copy

[…]一个更简单的方法是复制用于表示参数处理的va_list对象。然而,没有安全的方法在C89中这样做是因为对象可能包含指向由va_start宏分配并由va_end宏销毁的内存的指针。
新的va_copy宏提供了这种安全机制。

[…]

所以,是的,您需要在longjmp之前调用va_end。在这样的实现中,至少会出现内存泄漏。


假设Pyramid OSx有一个实现,其中内存分配由va_start执行。函数参数在寄存器中传递。即使对于可变函数也是如此。它可能早于ANSI C发明的函数原型,这意味着调用者不知道它是否在处理可变函数。va_start分配了内存,大概是为了存储函数参数值,以便va_arg可以轻松访问它。va_end释放分配的内存

它的va_startva_end的实现实际上需要在语法上匹配va_startva_end,因为它是使用不平衡花括号的,所以ANSI C已经禁止了这种实现,但是在使用匹配花括号的情况下可以使相同的原理工作。

我几乎找不到关于这个实现的具体信息,它只是80年代末90年代初Usenet上的一些零零碎碎的东西。我所发现的那一点可能是不完整的,甚至是完全错误的。更多的细节是非常受欢迎的,特别是那些自己使用这个实现的人。

如果您正在使用存储在全局变量中的jmp_buff(通常的模式),则应该安全地复制它并使用setjmp,以便longjmp将转到您的代码而不是外部调用者;在longjmp的情况下,你的代码可以使用缓冲区的存储副本调用va_endlongjmp;如果您的代码正常退出,则需要在返回之前恢复全局缓冲区。

相关内容

  • 没有找到相关文章

最新更新