在调用va_end之前,longjmp可以吗?

Hos*_*ork 11 c variadic-functions c89 language-lawyer longjmp

在此问答中,您应该始终致电va_end():

va_end究竟是什么?是否总是需要打电话给它?

但是如果你到达va_end之前有一段代码longjmp呢?va_end的部分是否有任何承诺可以接受?或者从概念上讲(例如)va_start()可能会泄漏内存分配,而不仅仅是使用堆栈技巧?

小智 8

C99理由明确规定,va_start可分配内存最终被释放va_end,你在你的问题猜到了什么:

7.15.1.2 va_copy

[...]

30一种更简单的方法是复制va_list用于表示参数处理的对象.但是,在C89中没有安全的方法可以执行此操作,因为该对象可能包含指向由va_start宏分配并由宏销毁的内存的指针va_end.
va_copy宏提供了这种安全机制.

[...]

所以是的,你需要va_end在a之前调用longjmp.至少你会在这样的实现上发生内存泄漏.


据说金字塔OSx有一个实现内存分配的实现va_start.函数参数在寄存器中传递.即使对于可变函数也是如此.它可能早于ANSI C发明的函数原型,这意味着调用者不知道它是否处理可变函数.va_start分配内存,大概是以一种va_arg可以轻松访问它的方式存储函数参数值.va_end释放分配的内存.

它的实现va_startva_end实际需要匹配va_startva_end语法,因为它是一个使用不平衡的括号,所以ANSI C已经不允许该实现,但同样的原则可以在匹配括号时工作.

我可以找到关于这个实现的非常少的具体信息,它在80年代末,90年代早期的Usenet上只是点点滴滴.我找到的一点点可能是不完整的,甚至是完全错误的.更多细节非常受欢迎,尤其是那些自己使用此实现的人.

  • 我认为值得引用`va_end`基本原理包含`在许多实现中,这是一个无操作的操作; 但那些需要它的实现可能需要它很糟糕.`badly`虽然很模糊. (2认同)