1

当我终于意识到问题是从多个线程调用 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

4 回答 4

2

SUSv2 说(线程):

本规范定义的所有接口都是线程安全的,除了以下接口不需要是线程安全的

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

这并不是说 iPhone 与 SUSv2 兼容,但我认为至少它解释了为什么您的代码应该可以在 Snow Leopard 上运行。此外,我手头没有更新的 POSIX 规范,所以我冒了一点风险假设它自 1997 年以来没有改变。

于 2009-12-22T01:29:01.497 回答
0

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

于 2009-12-22T07:40:00.123 回答
0

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

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

于 2009-12-22T01:16:45.857 回答
0

谢谢约翰和斯蒂芬!

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

于 2009-12-22T01:33:03.953 回答