c - 在调用 va_end 之前进行 longjmp 可以吗?

标签 c language-lawyer c89 setjmp variadic-functions

在此问答中,您应始终调用 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 the va_start macro and destroyed by the va_end macro.
The new va_copy macro provides this safe mechanism.

[...]

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


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

va_startva_end 的实现实际上需要在语法上匹配 va_startva_end,因为它是一个使用了不平衡的大括号,因此 ANSI C 已经不允许该实现,但是在具有匹配大括号的情况下可以使相同的原则起作用。

关于这个实现我能找到很少的具体信息,它只是 80 年代末 90 年代初 Usenet 上的零碎信息。我所发现的一点点可能是不完整的,甚至是完全错误的。欢迎提供更多详细信息,尤其是那些自己使用过此实现的人。

关于c - 在调用 va_end 之前进行 longjmp 可以吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32259543/

相关文章:

c - Visual Studio 2010 不缩进 C 代码

c - 我怎样才能找到这段代码中的漏洞?

c - 尝试刷新缓存时出现段错误(核心转储)错误

c++ - result_of 用于具有 cv 限定参数的成员对象

C积分溢出?

c - 尝试使用 C qsort 函数时出现问题

c - C 中一个枚举最多可以包含多少个元素?

c - 在for中声明结构?

c++ - 无限 std::chrono::duration 对象合法吗?

c - system (3) 命令的常见用途是什么?