是va_start(等)可重入吗? [英] Is va_start (etc.) reentrant?

查看:983
本文介绍了是va_start(等)可重入吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在对具有悠久历史的类进行编辑时,我被建筑师的一种特殊习惯阻碍了他的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();
}

这是从多个线程调用的。

c> c> c> c> > va_start 是安全的 foo()调用 bar() va_start ),答案是很好 - 只要 va_list 实例不一样。标准说,


不会调用va_start和va_copy宏来重新初始化ap,而不会干扰对同一个ap的va_end宏的调用。


所以,只要不同的 va_list



如果通过可重入意味着线程安全(我假设你是,因为互斥体涉及),你需要查看实现的细节。由于C标准没有谈到多线程,这个问题是真的由实现来确保。我可以想象,在一些奇怪的或小的架构上,可能很难使 va_start 线程安全,但我想如果你在一个现代主流平台上工作可能没有问题。



在更多的主流平台上,只要不同的 va_list va_start 宏你应该没有问题,多个线程通过'same' va_start 。因为 va_list 参数通常在栈上(因此不同的线程将有不同的实例),你通常处理 va_list的不同实例



我认为在您的示例中,互斥体对于varargs的使用是不必要的。但是,如果 write(),那么对于 write()调用序列化,你没有多个 write()线程拧紧彼此的输出。


While making an edit to a class with a long history, I was stymied by a particular habit of the architect of wrapping his va_start -> va_end sequence in a mutex. The changelog for that addition (which was made some 15 years ago, and not revised since) noted that it was because va_start et. all was not reentrant.

I was not aware of any such issues with va_start, as I always thought it was just a macro for some stack-pointer math. Is there something here I'm not aware of? I don't want to change this code if there will be side-effects.

Specifically, the function in question looks a lot like this:

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

This is called from multiple threads.

解决方案

As far as being serially-reentrant (ie., if foo() uses va_start is it safe for foo() to call bar() which also uses va_start), the answer is that's fine - as long as the va_list instance isn't the same. The standard says,

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.

So, you're OK as long as a different va_list (referred to above as ap) is used.

If by reentrant you mean thread-safe (which I assume you are, since mutexes are involved), you'll need to look to the implementation for the specifics. Since the C standard doesn't talk about multi-threading, this issue is really up to the implementation to ensure. I could imagine that it might be difficult to make va_start thread-safe on some oddball or small architectures, but I think if you're working on a modern mainstream platform you're likely to have no problems.

On the more mainstream platforms as long as a different va_list argument is being passed to the va_start macro you should have no problem with multiple threads passing through the 'same' va_start. And since the va_list argument is typically on the stack (and therefore different threads will have different instances) you're generally dealing with different instances of the va_list.

I think that in your example, the mutexes are unnecessary for the varargs use. However, if the write(), it certainly would make sense for a write() call to be serialized so that you don't have multiple write() threads screwing up each other's output.

这篇关于是va_start(等)可重入吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆