2011-01-07 280 views
15

我知道strtol和strtof比atoi/atof更受歡迎,因爲前者檢測錯誤,並且strtol比atoi更靈活,當涉及非base-10時。我仍然對好奇:OS X上的'man atoi'(或atof)(儘管不是在Linux上!)提到atoi/atof並不是線程安全的。坦率地說,我很難想象atoi或atof的可能實現不會是線程安全的。有人知道手冊頁爲什麼這麼說嗎?這些功能在OS X或任何其他平臺上實際上是不安全的嗎?如果是這樣,爲什麼地圖庫不會僅僅根據strtol定義atoi,因此是安全的?爲什麼OSX文件atoi/atof不是線程安全的?

+3

有趣的問題... – ChristopheD 2011-01-07 23:48:49

+0

大多數atoi實現只是strtol包裝它似乎。 – Anycorn 2011-01-07 23:54:43

+0

我已更改此問題的標題,以便至少提供一個有效的問題。 – 2011-01-07 23:55:32

回答

3

在在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); 

說明

atof()函數將str指向的字符串的起始部分轉換爲double表示。

它等效於:

 strtod(str, (char **)NULL); 

小數點字符在程序的語言環境(類別LC_NUMERIC)所定義。

雖然atof()函數使用當前語言環境,但atof_l()函數可能會直接傳遞到語言環境。有關更多信息,請參閱xlocale(3)。

實現注意

atof()函數不是線程安全的,也不是異步取消安全。

atof()函數已被strtod()棄用,且不應在新代碼中使用。

錯誤

功能atof()不必影響到一個錯誤的errno值。

我懷疑如果在執行atof()函數時當前語言環境被另一個線程更改,結果不能保證。否則,似乎沒有理由提出警告。


我探討了Darwin C庫源代碼的確切位置,但沒有找到一個。如果你去爲atoi() FreeBSD的源代碼,很顯然,該功能實現很簡單:

int 
atoi(str) 
    const char *str; 
{ 
    return (int)strtol(str, (char **)NULL, 10); 
} 

(是的,甚至沒有使用原型定義!)

strtol()手冊頁不具有關於線程安全性或異步取消安全性的黃鼠狼字眼。然而,快速瀏覽一下strtol()的源代碼顯示,它使用isspace(),這是由區域設置的影響:

ISO/IEC 9899:1999,第7.11.1.1 setlocale函數

7.4中唯一不受當前語言環境影響的函數是isdigit和isxdigit。

(其中§7.4是<ctype.h>。)

現在,雖然我不知道這個代碼是相同的什麼在達爾文(MacOS X系統),它很可能是相似的。我認爲手冊頁中可能存在勘誤的空間 - 目前尚不清楚需要更正的頁面是否爲atoi()strtol()的頁面。

atoi()
-3

這個問題的前提(在我編輯標題之前,它的原始形式)是錯誤的。它們是線程安全的。 POSIX指定所有函數都是線程安全的,除非另有說明(POSIX),並且文檔沒有說明這些函數不是線程安全的。 OSX聲稱符合POSIX,所以它們在OSX上是線程安全的,否則這是一個錯誤和主要一致性問題。我會認爲它只是在手冊頁中的一個錯誤...

0

一個猜測是這些函數沒有設置線程安全的方式errno,但這意味着一些奇怪的事情正在對馬科斯和errno進行和線。通常errno是一個線程局部變量。

1

經過一番研究,我認爲這只是遺留下來的舊時代errno是一個全球變量。如果檢查的FreeBSD errno.hhistoryfirst revision開始,你會看到,它最初被定義爲

extern int errno;   /* global error number */ 

,現在它是一個功能。我真的無法想到任何其他原因。

雖然atoi始終圍繞strtol包裝,它也設置errno,並應具有相同的線程安全性。它必須只是一個文檔問題。

2

Here's the implementation在蘋果的libc(atof()是相似的):

int 
atoi(str) 
    const char *str; 
{ 
    return (int)strtol_l(str, (char **)NULL, 10, __current_locale()); 
} 

而且strtol()

long 
strtol(const char * __restrict nptr, char ** __restrict endptr, int base) 
{ 
    return strtol_l(nptr, endptr, base, __current_locale()); 
} 

既然人與strtol沒有提到一個線程安全問題與strtol(),你可能得出以下幾個結論中的一個或多個:

  • 的文檔是錯atoi()是線程安全的,
  • 他們卻隻字不提,strtol()也是線程不安全,
  • 他們通過記錄該atoi()不作任何線程安全的承諾是保守的,即使當前實現恰好是線程安全的,
  • 他們是過時的(被錯誤的特殊情況,我想)

__current_locale()返回指向描述線程的區域(不出所料)的結構。但是,如果尚未設置線程特定的區域設置,則返回指向全局區域設置結構的指針。我認爲與全球交易可能是線程不安全的,但這個問題也適用於strtol()

1

這個答案是在問題提出幾年後,第一次回答。在我的Mac OS X 10.8.3(大約2013年3月),man atoi(或man atof)讀取:

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. 

所以最後一句話是可能是從來就沒有在這裏一個線程安全的問題,只有在文檔中的錯誤。

相關問題