在此问答中,您应始终调用 va_end()
:
What exactly is va_end for? Is it always necessary to call it?
但是如果在到达 va_end 之前有一段代码 longjmp 怎么办? va_end 是否 promise 一切都会好起来的?或者在概念上 (例如) 在 va_start()
中进行内存分配会泄漏,而不是仅使用堆栈技巧?
最佳答案
C99 rationale明确指出 va_start
可能会分配最终由 va_end
释放的内存,这正是您在问题中猜到的:
7.15.1.2 The
va_copy
macro[...]
30 A much simpler approach is to copy the
va_list
object used to represent processing of the arguments. However, there is no safe way to do this in C89 because the object may include pointers to memory allocated by theva_start
macro and destroyed by theva_end
macro.
The newva_copy
macro provides this safe mechanism.[...]
是的,您需要在 longjmp
之前调用 va_end
。至少你会在这样的实现上发生内存泄漏。
据说 Pyramid OSx 有一个实现,其中内存分配由 va_start
执行。函数参数在寄存器中传递。即使对于可变参数函数也是如此。它可能早于 ANSI C 发明的函数原型(prototype),这意味着调用者不知道它是否在处理可变参数函数。 va_start
分配的内存,大概是为了以 va_arg
可以轻松访问的方式存储函数参数值。 va_end
释放了分配的内存。
va_start
和 va_end
的实现实际上需要在语法上匹配 va_start
和 va_end
,因为它是一个使用了不平衡的大括号,因此 ANSI C 已经不允许该实现,但是在具有匹配大括号的情况下可以使相同的原则起作用。
关于这个实现我能找到很少的具体信息,它只是 80 年代末 90 年代初 Usenet 上的零碎信息。我所发现的一点点可能是不完整的,甚至是完全错误的。欢迎提供更多详细信息,尤其是那些自己使用过此实现的人。
关于c - 在调用 va_end 之前进行 longjmp 可以吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32259543/