Почему OSX документирует atoi / atof как не поддерживающую потоки? - PullRequest
15 голосов
/ 08 января 2011

Я понимаю, что strtol и strtof предпочтительнее atoi / atof, поскольку первые обнаруживают ошибки, а также strtol гораздо более гибкие, чем atoi, когда речь идет о неосновной-10.

Но мне все еще любопытно кое-что: «man atoi» (или atof) в OS X (хотя и не в Linux!) Упоминает, что atoi / atof не являются поточно-ориентированными. Мне, честно говоря, трудно представить возможную реализацию atoi или atof, которая не была бы поточно-ориентированной. Кто-нибудь знает, почему на странице руководства это сказано? Эти функции на самом деле небезопасны на OS X или любой другой платформе? И если это так, то почему библиотека не может просто определить atoi в терминах strtol и, следовательно, быть в безопасности?

Ответы [ 6 ]

4 голосов
/ 08 января 2011

Взглянув на страницу руководства в MacOS X 10.6.6, она документирует две функции, atof() и atof_l(), и я подозреваю, что дает подсказку о том, почему функция считается поточно-ориентированной:

SYNOPSIS

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

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

ОПИСАНИЕ

Функция atof() преобразует начальную часть указанной строкиот str до двойного представления.

Это эквивалентно:

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

Символ десятичной точки определен в локали программы (категория LC_NUMERIC).

В то время какФункция atof() использует текущую локаль, функция atof_l() может быть передана непосредственно в локаль.См. Xlocale (3) для получения дополнительной информации.

ЗАМЕЧАНИЯ ПО РЕАЛИЗАЦИИ

Функция atof() не является поточно-ориентированной и не асинхронно-отменяемой-безопасной.

Функция atof() устарела strtod() и не должна использоваться в новом коде.

ОШИБКИ

Функция atof() необходимане влияет на значение errno при ошибке.

Я подозреваю, что если текущий языковой стандарт изменяется другим потоком во время выполнения функции atof(), результат не гарантируется.В противном случае, кажется, нет никаких причин для предупреждения.


Я искал определенное местоположение исходного кода библиотеки Darwin C, но не нашел его.Если вы перейдете к исходному коду FreeBSD для atoi(), станет ясно, что реализация функции тривиальна:

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

187 Единственными функциями в 7.4, на поведение которых не влияет текущий языковой стандарт, являются isdigit и isxdigit.

(Где §7.4 для <ctype.h>.)

Теперь, хотя я не уверен, что этот код идентичен тому, что в Дарвине (MacOS X), он, вероятно, будет похожим.Я думаю, что на страницах руководства может быть место для ошибок - не очень понятно, является ли страница, которая нуждается в исправлении, страницей для atoi() или страницей для strtol().

2 голосов
/ 27 марта 2013

Этот ответ спустя пару лет после того, как был задан вопрос и дан первый ответ. На моем Mac OS X 10.8.3 (около марта 2013 г.) 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.

Таким образом, последнее слово, вероятно, заключается в том, что здесь никогда не было проблем с безопасностью потоков, только ошибки в документации.

2 голосов
/ 08 января 2011

Вот реализация из atoi() в libc от Apple (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());
}

Так как man strtol не упоминает о проблеме безопасности потоков с strtol(), вы можете сделать один или несколько из следующих выводов:

  • документы ошибочны из-за того, что atoi() небезопасен,
  • они пренебрегают упоминанием того, что strtol() также небезопасен для потоков,
  • они консервативны, документально подтверждая, что atoi() не дает никаких обещаний по безопасности потоков, даже если текущая реализация происходитчтобы быть потокобезопасными,
  • они устарели (частный случай неправильности, я полагаю)

__current_locale() возвращает указатель на структуру, описывающую локаль потока(неудивительно).Однако, если не определен языковой стандарт для потока, __current_locale() возвращает указатель на глобальную структуру языкового стандарта.Я предполагал, что работа с глобальными объектами может быть небезопасной, но тогда эта проблема будет распространяться и на strtol().

2 голосов
/ 08 января 2011

После некоторого исследования я думаю, что это просто наследие от старых времен, когда errno была глобальной переменной.Если вы проверите FreeBSD errno.h history , начиная с первой ревизии , вы увидите, что она изначально была определена как

extern int errno;           /* global error number */

и теперь это функция,Я не могу думать ни о какой другой причине на самом деле.

Хотя atoi всегда был оберткой вокруг strtol, которая также устанавливает errno и должна иметь такую ​​же безопасность потока.Это должно быть просто проблема с документацией.

0 голосов
/ 08 января 2011

Можно предположить, что эти функции не устанавливают errno потокобезопасным способом, но это означает, что что-то странное происходит с errno в macos и thread. Обычно errno является локальной переменной потока.

0 голосов
/ 08 января 2011

Предпосылка этого вопроса (в первоначальном виде до того, как я отредактировал название) неверна. Они потокобезопасны. POSIX указывает, что все функции являются поточно-ориентированными, если не документировано иное (POSIX), и в документации ничего не говорится об этих функциях, не являющихся поточно-ориентированными. OSX подразумевает соответствие POSIX, поэтому они ориентированы на многопоточность в OSX, иначе это ошибка и серьезная проблема соответствия. Я собираюсь предположить, что это просто ошибка в справочных страницах ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...