gpt4 book ai didi

c++ - va_start(等)是可重入的吗?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:17:27 35 4
gpt4 key购买 nike

在对历史悠久的类进行编辑时,我被架构师的一个特殊习惯所困扰,他将 va_start -> va_end 序列包装在互斥锁中。该添加的更改日志(大约 15 年前制作,此后没有修改)指出这是因为 va_start 等。一切都不可重入。

我不知道 va_start 有任何此类问题,因为我一直认为它只是一些堆栈指针数学的宏。这里有什么我不知道的吗?如果有副作用,我不想更改此代码。

具体来说,有问题的函数看起来很像这样:

void write(const char *format, ...)
{
mutex.Lock();
va_list args;
va_start(args, format);
_write(format, args);
va_end(args);
mutex.Unlock();
}

这是从多个线程调用的。

最佳答案

就串行可重入而言(即,如果 foo() 使用 va_start 调用 foo() 是否安全bar() 也使用 va_start),答案是没问题 - 只要 va_list 实例不一样。标准说,

Neither the va_start nor va_copy macro shall be invoked to reinitialize ap without an intervening invocation of the va_end macro for the same ap.

因此,只要使用不同的 va_list(在上面称为 ap)就可以了。

如果您所说的可重入是指线程安全的(我假设您是线程安全的,因为涉及互斥锁),您需要查看具体实现。由于 C 标准没有谈到多线程,这个问题真的要由实现来确保。我可以想象,在一些古怪的或小型架构上使 va_start 线程安全可能很困难,但我认为如果您在现代主流平台上工作,您可能不会遇到任何问题。

在更主流的平台上,只要将不同的 va_list 参数传递给 va_start 宏,多个线程通过“相同”传递应该没有问题va_开始。由于 va_list 参数通常在堆栈上(因此不同的线程将有不同的实例),您通常会处理 va_list 的不同实例。

我认为在您的示例中,互斥锁对于可变参数的使用是不必要的。但是,如果 write(),将 write() 调用序列化肯定是有意义的,这样您就没有多个 write() 线程搞砸了彼此的输出。

关于c++ - va_start(等)是可重入的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3865713/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com