2

私は単純なQR コードジェネレーターを作成しており (楽しみと Obj-C の学習のため)、接続された "モジュール" (つまり、QR コードを構成する黒い四角形) のアウトラインをトレースする作業を行っています。これは、単純にモジュールごとに多数の四角形を作成するよりも優れたベクトル出力を得るためです。

簡単に言うと、私のアウトライン トレース コードは機能しますが、特定の場所で NSLog を確実に呼び出す場合にのみ機能します。-callを削除するNSLogと、コードがループします。私は文字通り、ログ記録以外は何もしていません。何をログに記録するかは問題ではありません。NSLog を呼び出す必要があるか、問題が発生します。

トレース アルゴリズムは単純です。接続されたモジュールの形状を時計回りに進みます。角にぶつかったら、形状の輪郭に戻るまで右に曲がります。再び開始点に到達したら停止します。シェイプには、コーナー ポイントを共有する 2 つのモジュールを含めることができます。したがって、トレース ループはそのポイントに 2 回到達します。これは予想されることであり、コードはそれを正しく処理しますNSLog

それ以外の場合、コードは特定のポイントを最初に見たときにコーナーであると判断し、2 回目にはコーナーではないと判断し、トレースがループします。何かがコーナーポイントであるかどうかの検出は、ポイントの x 座標と y 座標、およびモジュール オブジェクトの配列以外には依存しませんが、トレースの実行中にモジュールも配列も変更されないため、同じ x を指定すると、 y常に同じ結果が得られるはずです。そして、それは -私が呼び出す場合NSLog

がないNSLog場合、座標 (たとえば (10,9)) はすぐに角になり、その瞬間 (10,9) は突然角として識別されなくなります。しかし -call を使用するとNSLog、(10,9) は常にコーナーポイントとして正しく認識されます。

繰り返しますが、私はまったく何も変更しません。私はただ何かを記録します - 何でも!そして突然それは機能します。2 == 2 が trueまたはfalse であると言っているようなものです。ただし、2 と 2 をログに記録するように指示しない限り、その場合、2 == 2 は常に true である必要があります。

これが不安定なコードです。文脈がわからなくてわかりにくいですが、文脈がたくさんあるので、これで十分だと思います。すべてが整数です (ファジー浮動小数点値はありません)。

do { // start going around the shape

    // If this isn't here or simply commented out, the code loops.
    NSLog(@"foobar"); // doesn't matter what I log - I just need to log something

    // Branch: Is current x,y a corner-point? This should
    // always return the same result given the same X and Y
    // values, but it only does if NSLog is there!
    if( [self cornerAtX:x Y:y] ) {

        // add the point to the path
        [path addPoint:NSMakePoint(x, y)];

        // rotate the direction clockwise, until
        // the direction is following the edge of the
        // the shape again.
        do {
            dt = dx;
            dx = -dy;
            dy = dt;
        } while( ![self boundaryFromX:x Y:y inDirectionX:dx Y:dy] );
    }

    // continue along direction
    x += dx;
    y += dy;

} while( !(sx == x && sy == y) ); // we're back to the start of the shape, so stop

なぜ NSLog がコードを機能させることができるのか (または、なぜNSLog を使用しないとコードが機能しなくなるのか) を誰かが教えてくれれば、喜んでそれを聞きます! 誰かがそれを理解できることを願っています。

4

3 に答える 3

7

cornerAtX:Y:常に何かを返すようにします。つまり、値を返さないコード パスがないことを確認します。

それ以外の場合、最後に呼び出した関数が返すものは何でも「返す」可能性が非常に高く、その場合、NSLog(値を返さないが、最終的に値を返す関数を呼び出す可能性があります) を呼び出すと、別のものを「返す」ことになります。常に真実と見なされるものであること。

宣言した関数またはメソッドから値を返さなかった場合、コンパイラは警告を発します。あなたはそれを聞くべきです。回避できるすべての警告をオンにして、それらすべてを修正します。

また、静的アナライザー (これもその投稿に含まれています) をオンにする必要があります。これも、このバグについて通知する可能性があるためです。

于 2010-11-22T07:58:36.060 に答える
2

ここで行うことはあまりありませんが、初期化されていない変数か、ある種のメモリ ストンピングのいずれかであると推測できます。NSLog はおそらくスタック メモリとヒープ メモリの両方を使用するため、それらに影響を与える可能性があります。

于 2010-11-22T07:47:26.627 に答える
0

NSLog を他の無意味な操作に置き換えてみましたか? それも機能する場合、問題は [self cornerAtX: x Y: y] にリンクされていると思います。もう 1 つの可能性は、問題が時間に関連しているということです。NSLog は実行に時間がかかるため、QR コードを別のスレッドでロードすると、このような動作が見られます。

于 2010-11-22T06:57:56.683 に答える