Является ли sscanf поточно-ориентированным на iPhone OS 3.1.2? - PullRequest
1 голос
/ 22 декабря 2009

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

Я подтвердил, выполнив следующий код, который работает, как и ожидалось, на Snow Leopard, но выдаеточень странные результаты на моем iphone с ОС 3.1.2.Он также отлично работает в симуляторе.

На iPhone разобранный номер будет несколько случайной комбинацией цифр, используемых в строках.

Было бы очень полезно, если бы кто-нибудь мог проверить,это общая проблема, или если это ошибка с моей стороны.

- (void)testIt
 {
    [NSThread detachNewThreadSelector:@selector(scanfTest) toTarget:self withObject:nil];
    [NSThread detachNewThreadSelector:@selector(scanfTest) toTarget:self withObject:nil];
}

- (void)scanfTest
{
    while (true)
    {
      float value = 0.0f;
      sscanf("456", "%f", &value);
      sscanf( "1.63", "%f", &value);
      if (value != 1.63f)
        NSLog(@"strange value is %f", value);
    }
}

Я провел дополнительную проверку, и оказалось, что только числа с плавающей запятой являются проблемой.
Этот код работает

- (void)scanfTest4
{
    while (true)
    {
        int year = 0;
        int month = 0;
        int day = 0;
        sscanf("20090131", "%4d%2d%2d", &year, &month, &day);
        sscanf("19840715", "%4d%2d%2d", &year, &month, &day);
        if (year != 1984 || month != 7 || day != 15)
            NSLog(@"bla");
    }
}

И этот код не работает с теми же случайными цифрами

- (void)scanfTest4
{
    while (true)
    {
        int year = 0;
        int month = 0;
        float day = 0.0f;
        sscanf("20090131", "%4d%2d%2f", &year, &month, &day);
        sscanf("19840715", "%4d%2d%2f", &year, &month, &day);
        if (year != 1984 || month != 7 || day != 15.0f)
            NSLog(@"bla");
    }
}

Ответы [ 4 ]

2 голосов
/ 22 декабря 2009

SUSv2 говорит ( Threads ):

Все интерфейсы, определенные этим спецификация будет поточно-ориентированной, кроме того, что следующие интерфейсы не должен быть потокобезопасным

sscanf() отсутствует в списке интерфейсов, которые не обязательно должны быть поточно-ориентированными.

Это не означает, что iPhone совместим с SUSv2, но я думаю, что по крайней мере это объясняет, почему ваш код должен работать на Snow Leopard. Кроме того, у меня нет более свежей спецификации POSIX, поэтому я рискну предположить, что она не изменилась с 1997 года.

0 голосов
/ 22 декабря 2009

Если я могу спросить, зачем вам использовать sscanf / atof, когда вы можете использовать числовые преобразования NSString?

0 голосов
/ 22 декабря 2009

Спасибо, Джон и Стивен!

Я могу подтвердить, что atof и strtof безопасны для использования в этой ситуации.

0 голосов
/ 22 декабря 2009

sscanf не является потокобезопасным ПЕРИОДОМ. он был написан до того, как существовали потоки, его дизайн требует использования внутренних статических временных переменных. То же самое относится и к спринту.

В твоем случае, sscanf все равно перебор. просто используйте atof вместо.

...