是sprintf线程安全吗?

时间:2012-11-14 19:58:46

标签: c linux multithreading

sprintf线程是否安全?

//Global log buffer 
char logBuffer[20];

logStatus (char * status, int length)
{
  snprintf(logBuffer, 19, status);
  printf ("%s\n", logBuffer);
}

此功能的线程安全性完全取决于snprintf / sprintf的线程安全性。

更新: 谢谢你的回答。 我不介意,如果实际内容gts搞砸了。但是当多个线程试图写入logBuffer时,想确认sprintf不会导致内存损坏/缓冲区溢出超过20个字节?

7 个答案:

答案 0 :(得分:15)

在多个线程中使用snprintf()没有问题。但是在这里你要写一个共享的字符串缓冲区,我假设它是跨线程共享的。

所以你使用这个函数是线程安全的。

答案 1 :(得分:3)

您的代码存在一些问题。

  1. 您对snprintf的使用非常可疑。不要只使用它 复制一个字符串。通常不传递动态分配的字符串 任何内容作为任何printf函数的格式。 他们解释内容,如果有什么内容 类似于%格式,你注定要失败。
  2. 不要像使用static缓冲区那样使用。这当然都不是 线程安全不可重入。
  3. 直接使用具有适当格式的printf,或替换 puts的电话。
  4. 然后,Linux遵循POSIX标准,这要求标准IO功能是线程安全的。

答案 2 :(得分:2)

您的问题有不正确的前提。即使sprintf本身可以同时从多个线程安全地调用(我希望它可以),但是你的代码并没有保护你的全局变量。标准库不可能帮助你。

答案 3 :(得分:2)

关于您的更新,不要担心logBuffer内容是否会出现乱码:

我不确定你为什么要通过使用本地分配的缓冲区或某种同步机制来避免让你的函数完全保持线程安全,但是如果你想知道POSIX对它的评价,那么你去({{ 3}}):

  

应用程序应确保限制多个控制线程(线程或进程)对任何内存位置的访问,以便没有控制线程可以读取或修改内存位置,而另一个控制线程可能正在修改它。使用同步线程执行的函数以及相对于其他线程同步存储器来限制这种访问。 [后跟提供同步的功能列表]

所以,POSIX说你的程序需要确保多个线程不会同时修改logBuffer(或者在一个线程中修改logBuffer而在另一个线程中修改它时)。如果你不坚持这一点,那么就没有承诺将会发生的最坏情况是logBuffer中的乱码数据。根本没有任何关于结果的承诺。我不知道Linux是否可以记录更具体的行为,但我对此表示怀疑。

答案 4 :(得分:2)

“在多个线程中使用snprintf()没有问题。”

不正确。

不正确,至少在POSIX功能的情况下。

所有标准vararg函数都不是安全的 - 这包括所有printf()系列(1),还包括其他所有variadic函数(2)

  1. sprintf()例如:“MT-Safe locale | AS-Unsafe heap | AC-Unsafe mem” - 意味着,如果异步设置locale或线程异步取消,它可能会失败用来。换句话说,在MT环境中使用此类功能时必须特别注意。

  2. va_arg不安全:| MT-Safe race:ap | AS-Safe | AC-Unsafe corrupt | - 什么意思,需要互锁。

  3. 此外,显而易见的是,甚至完全mt-safe函数也可以以不安全的方式使用 - 例如,如果两个或多个线程正在运行相同的数据/内存区域,会发生什么。

答案 5 :(得分:0)

它不是线程安全的,因为sprintf的缓冲区在所有线程之间共享。

答案 6 :(得分:0)

"您是否有参考说明他们不是线程安全的?当我谷歌时,它们似乎是"

我之前对此问题的回答已被删除/删除(为什么?),所以我将尝试使用不同的方法:

  1. AC(异步。取消线程):这显然是几乎所有显然是MT安全的#34;代码可能会失败,原因很简单,因为线程在随机时间点被中断,因此没有任何同步方法可以保证正常工作(即任何形式的互斥锁都无法保证正常工作)

    < / LI>
  2. 线程可以使用相同的malloc()竞技场,这意味着,如果其中一个线程失败(即它会损坏malloc竞技场),那么对malloc()的所有连续调用将/可能会导致严重错误 - 这当然取决于系统配置 - 但这也意味着,没有人应该认为格式错误的内存(de)分配是安全的。

  3. 由于所有系统都提供了使用不同本地设置的选项,因此显然是异步。更改为&#34;区域设置&#34;设置可能会导致错误...

    问候。