Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为什么OSX记录atoi/atof不是线程安全的?_C_Macos - Fatal编程技术网

C 为什么OSX记录atoi/atof不是线程安全的?

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,从而保证安全呢 这

我知道strtol和strtof比atoi/atof更受欢迎,因为前者可以检测错误,而且strtol在非base-10方面比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
是一个全局变量时遗留下来的。如果从开始检查FreeBSD
errno.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.