在iPhone OS 3.1.2上sscanf是否是线程安全的?

时间:2009-12-22 01:04:24

标签: iphone c thread-safety scanf

当我终于意识到问题是从多个线程调用sscanf时,我只是花了整整一天调试一个随机错误。

我通过运行以下代码确认,它在Snow Leopard上按预期工作,但在我的iphone上使用os 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 个答案:

答案 0 :(得分:2)

SUSv2说(Threads):

  

由此定义的所有接口   规范将是线程安全的,   除了以下接口   不必是线程安全的

sscanf()不在不需要线程安全的接口列表中。

这并不是说iPhone符合SUSv2标准,但我认为至少它解释了为什么你的代码应该适用于Snow Leopard。此外,我手边没有更新的POSIX规范,所以假设自1997年以来没有改变,我冒了一点风险。

答案 1 :(得分:0)

sscanf不是线程安全的PERIOD。它是在线程存在之前编写的,其设计要求它使用内部静态临时变量。 sprintf也是如此。

我是你的情况,无论如何,sscanf都是矫枉过正的。只需使用atof

答案 2 :(得分:0)

谢谢John和Stephen!

我可以确认atof和strtof在这种情况下都可以安全使用。

答案 3 :(得分:0)

如果我可能会问,为什么在使用NSString数字转换时需要使用sscanf / atof?