1

問題が複数のスレッドから呼び出されている sscanf であることに最終的に気付いたとき、ランダムなバグのデバッグに丸一日を費やしていました。

次のコードを実行して、Snow Leopard では期待どおりに動作することを確認しましたが、OS 3.1.2 の iPhone では非常に奇妙な結果が生成されます。シミュレーターでも問題なく動作します。

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

ジョンとスティーブン、ありがとう!

この状況では、atof と strtof の両方を使用しても安全であることを確認できます。

于 2009-12-22T01:33:03.953 に答える
0

sscanf はスレッドセーフ PERIOD ではありません。スレッドが存在する前に書かれたもので、その設計では内部の静的一時変数を使用する必要があります。同じことがsprintfにも当てはまります。

あなたの場合、とにかくsscanfはやり過ぎです。atof代わりに使用してください。

于 2009-12-22T01:16:45.857 に答える
0

NSString 数値変換を使用できるのに、なぜ sscanf/atof を使用する必要があるのでしょうか?

于 2009-12-22T07:40:00.123 に答える