Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在iPhone OS 3.1.2上sscanf线程安全吗?_Iphone_C_Thread Safety_Scanf - Fatal编程技术网

在iPhone OS 3.1.2上sscanf线程安全吗?

在iPhone OS 3.1.2上sscanf线程安全吗?,iphone,c,thread-safety,scanf,Iphone,C,Thread Safety,Scanf,我刚刚花了一整天的时间调试一个随机bug,这时我终于意识到问题是sscanf被多个线程调用了 我通过运行以下代码确认了这一点,该代码在SnowLeopard上正常工作,但在我的iphone上使用os 3.1.2会产生非常奇怪的结果。它也可以在模拟器中正常工作 在iPhone上,解析的数字将是字符串中使用的数字的随机组合 如果有人能检查一下这是不是一个普遍的问题,或者这是我这边的一个错误,那将是非常有帮助的 - (void)testIt { [NSThread detachNewThre

我刚刚花了一整天的时间调试一个随机bug,这时我终于意识到问题是sscanf被多个线程调用了

我通过运行以下代码确认了这一点,该代码在SnowLeopard上正常工作,但在我的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");
    }
}

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

我知道你的情况,不管怎么说,sscanf的杀伤力太大了。只需使用
atof

SUSv2说():

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

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


这并不是说iPhone是SUSv2兼容的,但我认为至少它解释了为什么你的代码应该在雪豹上工作。另外,我手头上没有最新的POSIX规范,所以我冒着一点风险假设它自1997年以来没有改变。

谢谢John和Stephen


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

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

您看到的输出与期望的输出相比是什么?比较2个浮点值(即:1.63==1.63)本身就充满了困难。要基于Jarret Hardie的评论:而不是直接比较浮点值是否相等,通常需要用一个小的(1e-6)ε进行一些
if(fabs(float1-float2)
。这告诉你它们是否足够接近,可以被认为是相等的,而不是完全相同的。正如我所提到的,我得到的输出是从1到1456或13.6的任何数字,或者可以由数字“456”“1.63”组合的任何数字,我知道我知道。。。问题是,如果我不使用sscanf(“456”、“%f”、&value);所有的一切都如预期的那样工作,所以很明显,内部状态是共享的。只要两个线程扫描相同的字符串,一切都很好。不要使用atof。改用标准的C
strof()
函数,该函数具有更简单的错误处理,通常更易使用。您能解释一下sscanf的定义中要求它使用静态变量的是什么吗?@Steve Jessop,它不需要,但它需要跟踪它在格式字符串中的长度等等。我想,仅仅使用一个静电传感器是很容易的。“但我有点被提问者得到的结果难住了。”史蒂夫·杰索普。所以可能要求太强了。当然可以想象一个不使用静态的实现。但它确实需要一个相当大的临时存储空间,并且它调用了许多其他crt代码作为帮助。典型的实现是将输入字符串转换为一个“假装”文件,然后将其传递给fscanf(或者更确切地说,它和fscanf共享一个公共worker)。删除原始crt中的所有静态是一项相当艰巨的工作,你仍然无法保护自己免受缓冲区溢出的影响。如果没有静态,我想你已经为OSX和模拟器做了。我也检查了SUSv2,因此对John的“sscanf不是线程安全期”感到有点困惑sscanf不是我所知道的POSIX函数之一。我希望它使用区域设置,这总是一个蠕虫线程,但您看到的行为更像是将部分输入复制到静态中。对我来说,这是令人费解的,但并不明显是疯狂的,所以也许我只是错过了一些显而易见的原因,为什么sscanf工作得更好/如果这样做的话。我注意到,NSScanner被明确定义为不是线程安全的。是否iPhone上的sscanf使用的是针对区域设置配置的全局NSScanner?我现在要停止猜测了,最终我对Mac和iPhone的了解大致如下:0;-)出于性能方面的原因,我决定在应用程序的这一部分严格使用C语言。我以前使用的cocoa版本无法进一步优化,而向C语言的转换带来了巨大的性能提升。