C 为什么OSX记录atoi/atof不是线程安全的?
我知道strtol和strtof比atoi/atof更受欢迎,因为前者可以检测错误,而且strtol在非base-10方面比atoi灵活得多C 为什么OSX记录atoi/atof不是线程安全的?,c,macos,C,Macos,我知道strtol和strtof比atoi/atof更受欢迎,因为前者可以检测错误,而且strtol在非base-10方面比atoi灵活得多 但我仍然对一些事情感到好奇:“OSX上的man-atoi”(或atof)(虽然不是Linux!)提到atoi/atof不是线程安全的。坦率地说,我很难想象atoi或atof的可能实现是线程安全的。有人知道为什么手册上会这样说吗?在OSX或任何其他平台上,这些功能实际上是不安全的吗?如果是的话,为什么图书馆不能用strtol来定义atoi,从而保证安全呢 这
但我仍然对一些事情感到好奇:“OSX上的man-atoi”(或atof)(虽然不是Linux!)提到atoi/atof不是线程安全的。坦率地说,我很难想象atoi或atof的可能实现是线程安全的。有人知道为什么手册上会这样说吗?在OSX或任何其他平台上,这些功能实际上是不安全的吗?如果是的话,为什么图书馆不能用strtol来定义atoi,从而保证安全呢 这个问题的前提(在我编辑标题之前的原始形式)是错误的。它们是线程安全的。POSIX指定所有函数都是线程安全的,除非另有说明(由POSIX提供),并且文档中没有说明这些函数不是线程安全的。OSX声称符合POSIX,所以它们在OSX上是线程安全的,否则这就是一个bug和主要的一致性问题。我将假设这只是手册页中的一个bug…一个猜测是,这些函数没有以线程安全的方式设置errno,但这意味着macos和线程上的errno出现了一些奇怪的情况。通常情况下,errno是一个线程局部变量。在做了一些研究之后,我认为它只是从过去的
errno
是一个全局变量时遗留下来的。如果从开始检查FreeBSDerrno.h
,您会看到它最初定义为
extern int errno; /* global error number */
现在它是一个函数。我真的想不出任何其他理由
尽管
atoi
始终是一个包装器,它还设置了errno
,因此应该具有相同的线程安全性。这一定只是一个文档问题。看看MacOS X 10.6.6上的手册页面,它记录了两个函数,atof()
和atof_l()
,我怀疑这会提示为什么该函数被认为是线程不安全的:
简介
#include <stdlib.h>
double atof(const char *str);
#include <xlocale.h>
double atof_l(const char *str, locale_t loc);
小数点字符是在程序的区域设置中定义的(类别LC\U NUMERIC)
当atof()
函数使用当前区域设置时,可以直接向atof_l()
函数传递区域设置。有关更多信息,请参见xlocale(3)
实施说明
#include <stdlib.h>
double atof(const char *str);
#include <xlocale.h>
double atof_l(const char *str, locale_t loc);
atof()
函数不是线程安全的,也不是异步取消安全的
strod()
已弃用了atof()
函数,不应在新代码中使用
错误
#include <stdlib.h>
double atof(const char *str);
#include <xlocale.h>
double atof_l(const char *str, locale_t loc);
函数atof()
无需影响出错时的errno
值
我的怀疑是,如果在执行atof()
函数时,另一个线程更改了当前区域设置,则无法保证结果。否则,似乎没有理由发出警告
我四处寻找达尔文C库源代码的确切位置,但还没有找到。如果您查看FreeBSD源代码,很明显函数实现非常简单:
int
atoi(str)
const char *str;
{
return (int)strtol(str, (char **)NULL, 10);
}
(是的,甚至不使用原型定义!)
strtol()
的手册页没有关于线程安全性或异步取消安全性的黄鼠狼措辞。但是,快速查看的源代码表明,它使用了受区域设置影响的isspace()
:
ISO/IEC 9899:1999,第7.11.1.1节设置语言环境功能
187 7.4中行为不受当前语言环境影响的函数只有isdigit和isxdigit
(其中§7.4表示
)
现在,虽然我不确定这段代码是否与Darwin(MacOS X)中的代码相同,但很可能是相似的。我认为手册页中可能有勘误的地方——不太清楚需要更正的页面是苹果libc中atoi()的atoi()
页面还是strtol()页面(atof()
类似):
和strtol()
:
由于man strtol没有提及strtol()
的线程安全问题,您可能会得出以下一个或多个结论:
- 文档错误地认为
是线程不安全的atoi()
- 他们忽略了提及
也是线程不安全的strtol()
- 他们保守地记录了
不保证线程安全,即使当前的实现恰好是线程安全的atoi()
- 它们已经过时了(我想这是一种特殊的错误)
\uu current\u locale()
返回一个指向描述线程区域设置的结构的指针(毫不奇怪)。但是,如果尚未设置线程特定的区域设置,\uu current\u locale()
将返回指向全局区域设置结构的指针。我认为处理全局线程可能是不安全的,但是这个问题也适用于strtol()。这个答案是在问题被提出并首次得到回答后的几年。在我的Mac OS X 10.8.3(大约2013年3月)上,man atoi
(或man atof
)的内容如下:
因此,最后一句话可能是这里从来没有线程安全问题,只有文档中的错误。大多数atoi实现似乎只是strtol包装器。我已经更改了这个问题的标题,因此它至少是一个有效的问题。嗯,可以想象一个非线程安全的实现:atof可以访问当前区域设置,如果另一个线程更改了区域设置,这可能是不安全的。然而,正如R。。指出,现在POSIX似乎要求atof是线程安全的。@Jukka:事实上,当一个线程正在使用
setlocale
时,调用任何依赖于区域设置的函数都会导致未定义的行为,但这被认为是独立的(
long
strtol(const char * __restrict nptr, char ** __restrict endptr, int base)
{
return strtol_l(nptr, endptr, base, __current_locale());
}
IMPLEMENTATION NOTES
The atof() and atof_l() functions are thread-safe and async-cancel-safe.
The atof() and atof_l() functions have been deprecated by strtod() and
strtod_l() and should not be used in new code.