2

我正在编写一个简单的QR 码生成器(只是为了好玩和学习一些 Obj-C),并且我正在跟踪连接的“模块”(即构成 QR 码的黑色方块)的轮廓。这是为了获得更好的向量输出,而不是简单地为每个模块制作一堆矩形。

长话短说,我的大纲跟踪代码有效——但前提是我确保在特定位置调用 NSLog!如果我删除NSLog-call,代码会循环!除了记录,我实际上什么都不做。我记录什么并不重要;我只需要调用 NSLog 否则事情就会中断。

跟踪算法很简单:围绕连接模块的形状顺时针移动。当你碰到一个角落时,向右转,直到你回到形状的轮廓。再次到达起点时停止。该形状可以有两个共享一个角点的模块。因此,跟踪循环将两次命中该点。这是预期的,并且代码可以正确处理它 -如果我调用NSLog.

否则,代码会在第一次看到某个点时说它是一个角,而第二次看到它不是一个角,这会导致跟踪循环。检测某个东西是否是角点不依赖于除了点的 x 和 y 坐标以及模块对象数组之外的任何东西——但是在跟踪进行时模块和数组都不会改变,所以给定相同的 x, y 你应该总是得到相同的结果。它确实如此——如果我打电话给NSLog.

如果没有NSLog,坐标(例如(10,9))是角上的瞬间,片刻之后(10,9)突然被识别为角。但是使用-call NSLog,(10,9)每次都被正确地视为角点。

再说一遍:我完全没有改变;我只是记录一些东西——任何东西!突然间它起作用了。这就像说 2 == 2 是真还是假,除非我告诉它记录 2 和 2,在这种情况下 2 == 2 总是正确的,因为它应该是。

这是片状代码。脱离上下文很难理解,但是有很多上下文,所以我希望这已经足够了。一切都是整数(没有模糊浮点值)。

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:总是返回一些东西——也就是说,没有代码路径不能返回一个值。

Otherwise, it may very well “return” whatever the last function you called returns, in which case calling NSLog (which doesn't return a value, but may ultimately call a function that does) causes it to “return” something different, which may always be something that's considered true.

The compiler should warn you if you fail to return a value from a function or method that you declared as doing so. You should listen to it. Turn on all the warnings you can get away with and fix all of them.

You should also turn on the static analyzer (also included in that post), as it, too, may tell you about this bug, and if it does, it will tell you step-by-step how it's happening.

于 2010-11-22T07:58:36.060 回答
2

这里没什么可做的,但我猜它要么是一个未初始化的变量,要么是某种内存踩踏。NSLog 可能同时使用堆栈和堆内存,因此它可能会影响它们。

于 2010-11-22T07:47:26.627 回答
0

你试过用其他一些无意义的操作替换 NSLog 吗?如果这也可行,那么我认为问题与 [self cornerAtX: x Y: y] 有关。另一种可能性是问题与时间有关。NSLog 执行需要时间,所以如果 QR 码在另一个线程中加载,您可以看到这种行为。

于 2010-11-22T06:57:56.683 回答