在本问答中,您应该始终致电va_end()
:
但是如果在你到达 va_end 之前有一段代码 longjmp 呢?va_end 是否有任何保证会好起来的承诺?或者从概念上讲,它(例如)可能会进行内存分配va_start()
,而不是仅使用堆栈技巧?
在本问答中,您应该始终致电va_end()
:
但是如果在你到达 va_end 之前有一段代码 longjmp 呢?va_end 是否有任何保证会好起来的承诺?或者从概念上讲,它(例如)可能会进行内存分配va_start()
,而不是仅使用堆栈技巧?
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
。至少你会在这样的实现上出现内存泄漏。
据说 Pyramid OSx 有一个实现,其中内存分配由va_start
. 函数参数在寄存器中传递。即使对于可变参数函数也是如此。它可能早于 ANSI C 对函数原型的发明,这意味着调用者不知道它是否在处理可变参数函数。分配的内存,大概是为了以可以轻松访问它va_start
的方式存储函数参数值。释放分配的内存。va_arg
va_end
它的实现实际上需要匹配va_start
和语法,因为它使用了不平衡的大括号,所以 ANSI C 已经不允许这种实现,但是在匹配大括号时可以使相同的原理起作用。va_end
va_start
va_end
我几乎找不到关于这个实现的具体信息,它只是 80 年代末、90 年代初在 Usenet 上的点点滴滴。我所发现的一点点可能是不完整的,甚至是完全错误的。非常欢迎提供更多详细信息,尤其是任何自己使用此实现的人。
如果您使用的是jmp_buff
存储在全局变量中的 a (通常的模式),那么制作它的副本并使用它应该是安全的,setjmp
因此longjmp
它将转到您的代码而不是外部调用者;在这种情况下longjmp
,您的代码可以调用va_end
并longjmp
使用缓冲区的存储副本;如果您的代码正常退出,则需要在返回之前恢复全局缓冲区。