2011-01-07 26 views
15

Tôi hiểu rằng strtol và strtof được ưu tiên so với atoi/atof, vì lỗi phát hiện trước đây và strtol linh hoạt hơn nhiều so với atoi khi nói đến non-base-10.Tại sao tài liệu OSX atoi/atof không phải là chủ đề an toàn?

Nhưng tôi vẫn tò mò về điều gì đó: 'man atoi' (hoặc atof) trên OS X (mặc dù không phải trên Linux!) Đề cập rằng atoi/atof không phải là chủ đề an toàn. Tôi thẳng thắn có một thời gian khó tưởng tượng một khả năng thực hiện của atoi hoặc atof mà sẽ không được an toàn. Có ai biết tại sao trang người đàn ông nói điều này? Các chức năng này có thực sự không an toàn trên OS X hay bất kỳ nền tảng nào khác không? Và nếu có, tại sao trên trái đất không phải thư viện chỉ xác định atoi về strtol, và do đó được an toàn?

+3

Câu hỏi thú vị ... – ChristopheD

+0

hầu hết các triển khai atoi chỉ là trình bao bọc strtol. – Anycorn

+0

Tôi đã thay đổi tiêu đề của câu hỏi này sao cho nó ít nhất là một câu hỏi hợp lệ. –

Trả lời

3

Lấy một cái nhìn tại các trang hướng dẫn trên hệ điều hành MacOS X 10.6.6, nó tài liệu hai chức năng, atof()atof_l(), và tôi nghi ngờ rằng đưa ra một gợi ý là tại sao hàm được coi là không thread-safe:

SYNOPSIS

#include <stdlib.h> 
double atof(const char *str); 

#include <xlocale.h> 
double atof_l(const char *str, locale_t loc); 

MÔ tẢ

Các Hàm atof() chuyển đổi phần ban đầu của chuỗi được trỏ tới bởi str thành biểu diễn kép.

Nó tương đương với:

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

Nhân vật dấu thập phân được xác định trong chương trình địa phương (loại LC_NUMERIC).

Trong khi chức năng atof() sử dụng ngôn ngữ hiện tại, chức năng atof_l() có thể được chuyển trực tiếp bằng ngôn ngữ. Xem xlocale (3) để biết thêm thông tin.

THI THUYẾT

Chức năng atof() không phải là thread-safe và cũng không async-hủy-an toàn.

Chức năng atof() không được dùng nữa bởi strtod() và không được sử dụng trong mã mới.

LỖI

Chức năng atof() không cần phải ảnh hưởng đến giá trị của errno về một lỗi.

Nghi ngờ của tôi là nếu ngôn ngữ hiện tại bị thay đổi bởi một chuỗi khác trong khi chức năng atof() đang thực thi, kết quả không được đảm bảo. Nếu không, có vẻ như không có lý do gì cho cảnh báo.


Tôi đã chọc xung quanh vị trí chính xác của mã nguồn thư viện Darwin C, nhưng chưa tìm thấy. Nếu bạn đi đến mã nguồn FreeBSD cho atoi(), rõ ràng là việc thực hiện chức năng là tầm thường:

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

(Vâng, thậm chí không sử dụng một định nghĩa prototyped!)

Các trang người đàn ông cho strtol() không có từ ngữ chồn về an toàn luồng hoặc an toàn-hủy bỏ an toàn. Tuy nhiên, một cái nhìn nhanh chóng vào mã nguồn cho strtol() cho thấy rằng nó sử dụng isspace(), mà bị ảnh hưởng bởi ngôn ngữ:

ISO/IEC 9899: 1999, Phần 7.11.1.1 Chức năng setlocale

Các hàm duy nhất trong 7.4 có hành vi không bị ảnh hưởng bởi ngôn ngữ hiện tại là isdigit và isxdigit.

(Trong trường hợp §7.4 là dành cho <ctype.h>.)

Bây giờ, trong khi tôi không chắc chắn rằng mã này giống hệt như những gì trong Darwin (hệ điều hành MacOS X), nó có khả năng là tương tự. Tôi nghĩ rằng có thể có chỗ cho errata trong các trang của người đàn ông - nó không phải là quá rõ ràng cho dù trang cần chỉnh sửa là một cho atoi() hoặc một cho strtol().

+0

Hàm 'setlocale' không an toàn và có thể không được gọi nếu bất kỳ luồng nào khác có thể ở trong một hàm có hành vi phụ thuộc vào ngôn ngữ. Tuy nhiên, các chức năng như vậy không được coi là không an toàn. Nhận xét về async-cancel-safety cũng có vẻ hơi lạ, vì POSIX khá rõ ràng là không có hàm nào ngoại trừ 'pthread_setcanceltype',' pthread_setcancelstate' và 'pthread_cancel' là async-cancel-safe. –

+0

Điều này rất có ý nghĩa. Đó là quá xấu các tài liệu không cụ thể hơn rằng nó an toàn miễn là ứng dụng của bạn không thay đổi miền địa phương (tôi chắc chắn là không). Tôi không có chuyên gia địa phương, nhưng tôi không chắc chắn tôi hiểu làm thế nào miền địa phương sẽ được sử dụng trong atoi (atof, tôi hiểu - dấu thập phân). –

+0

@Larry: 'atoi()' có thể đang xem xét dấu tách hàng nghìn và có lẽ là nhóm, tôi giả sử ... Tuy nhiên, hãy xem cập nhật của tôi cho câu trả lời của tôi. –

-3

Tiền đề của câu hỏi này (ở dạng ban đầu, trước khi tôi chỉnh sửa tiêu đề) là sai. Chúng an toàn chỉ. POSIX quy định rằng tất cả các chức năng đều an toàn chỉ trừ khi có tài liệu khác (bởi POSIX), và tài liệu không nói bất cứ điều gì về các chức năng này không an toàn chỉ. OSX purports để phù hợp với POSIX, vì vậy họ là thread-an toàn trên OSX hoặc người nào khác đây là một lỗi và vấn đề phù hợp lớn. Tôi sẽ giả định nó chỉ là một lỗi trong các trang của người đàn ông ...

+1

Vì vậy, câu trả lời của bạn là 'man atoi' là sai trên OSX? Điều đó không làm cho tiền đề của câu hỏi này sai. –

+1

Có. Đây sẽ không phải là lần đầu tiên một trang người bán hàng sai, hoặc là người cuối cùng. Tôi vẫn không biết tại sao họ khăng khăng viết những trang người đàn ông riêng của họ thay vì chỉ bao gồm những trang của POSIX ... –

+2

Ồ, và tôi là người thay đổi tiêu đề của câu hỏi. Câu hỏi ban đầu là "Tại sao atoi/atof không an toàn?" –

0

Một giả định là các chức năng này không đặt errno trong một chủ đề an toàn, nhưng điều đó có nghĩa là một cái gì đó kỳ lạ đang xảy ra với errno trên macos và chủ đề. Thông thường errno là một biến địa phương thread.

+4

Bạn sẽ phải đi ra khỏi con đường của bạn để viết một phiên bản mà không đặt 'errno' trong một cách an toàn thread, vì chỉ đơn giản là' errno = foo; 'là một cách hoàn toàn an toàn để thiết lập nó. –

+0

Assigment của bất cứ điều gì khác hơn là một bool không nhất thiết phải thread an toàn trong c (hoặc c + +) mà không có trình biên dịch cụ thể extentions –

1

Sau khi thực hiện một số nghiên cứu, tôi nghĩ đó chỉ là di sản từ những ngày cũ khi errno là một biến toàn cục. Nếu bạn kiểm tra FreeBSD errno.hhistory bắt đầu từ first revision, bạn sẽ thấy rằng nó đã được ban đầu được định nghĩa là

extern int errno;   /* global error number */ 

và bây giờ nó là một hàm. Tôi không thể nghĩ ra bất kỳ lý do nào khác.

Mặc dù atoi luôn là một trình bao bọc xung quanh strtol cũng đặt errno và sau đó sẽ có cùng độ an toàn cho luồng. Nó phải chỉ là một vấn đề tài liệu.

+0

Trên hệ thống Linux hiện đại, errno là thread-local, tức là mỗi thread có bản sao riêng của nó. –

2

Here's the implementation của atoi() trong libc của Apple (atof() là tương tự):

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()); 
} 

Kể từ khi người đàn ông strtol làm cho không có đề cập đến một vấn đề thread-an toàn với strtol(), có lẽ bạn rút ra một hoặc nhiều kết luận:

  • các tài liệu là sai về atoi() là thread-an toàn,
  • họ đang bỏ qua kể rằng strtol() cũng là chủ đề không an toàn,
  • họ đang là bảo thủ bằng cách ghi rằng atoi() làm cho không có lời hứa về chủ đề an toàn, ngay cả khi việc thực hiện hiện nay sẽ xảy ra là chủ đề an toàn,
  • họ trong ngày (trường hợp đặc biệt của là sai, tôi giả sử)

__current_locale() trả về một con trỏ đến một cấu trúc mô tả locale của chủ đề (không ngạc nhiên). Tuy nhiên, nếu một miền địa phương cụ thể không được thiết lập, __current_locale() trả về một con trỏ đến một cấu trúc miền địa phương toàn cục. Tôi cho là giao dịch với toàn cầu có thể không an toàn, nhưng vấn đề đó cũng sẽ áp dụng cho strtol().

+0

Đó là phiên bản FreeBSD. Có lý do chính đáng để tin rằng nó giống hệt nhau trên Mac OS X không? –

+1

Các clip đến từ một kho lưu trữ trên http://www.opensource.apple.com/source/Libc/Libc-583 –

1

Câu trả lời này là một vài năm sau khi câu hỏi được hỏi và trả lời lần đầu tiên. Trên Mac OS X 10.8.3 của tôi (khoảng tháng 3 năm 2013), man atoi (hoặc man atof) lần đọc:

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. 

Vì vậy, quyết định cuối cùng có lẽ rằng có bao giờ là một vấn đề thread-an toàn ở đây, chỉ có sai sót trong tài liệu hướng dẫn .

Các vấn đề liên quan