- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
在对历史悠久的类进行编辑时,我被架构师的一个特殊习惯所困扰,他将 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/
嗨,我已经阅读了 Java 中的 ReadWriteLock,但我不确定我是否掌握了它的重入部分。这是两个仅使用一个主线程来显示重入的简短代码示例 public class Locks { p
我在使用 NotifyIcons 时发现了一个重入问题。重现它真的很容易,只需在表单上放置一个 NotiftIcon,点击事件应该如下所示: private bool reentrancyDetect
我正在尝试使用 SQLite 的新 C 接口(interface)预更新 Hook : https://www.sqlite.org/c3ref/preupdate_count.html 现在回答我的
来自阅读here我发现 Actor 是可重入的,并且我希望以下情况成立:如果我有单一类型的转换 ThespianType 但有三个特定的 Actor ThespianType (T1、T2 和 T3)
有人可以向我解释一下 BlockReentrancy 的目的是什么吗?方法在ObservableCollection ? MSDN显示以下内容作为示例: //The typical usage is
我是一名优秀的程序员,十分优秀!