开发者

Code only works if I NSLog some values - but why?

开发者 https://www.devze.com 2023-01-26 01:22 出处:网络
I\'m writing a simple QR code generator (just for fun and to learn some Obj-C), and I\'m working on tracing the outline of connected \"modules\" (i.e. the black squares that make up a QR code). This i

I'm writing a simple QR code generator (just for fun and to learn some Obj-C), and I'm working on tracing the outline of connected "modules" (i.e. the black squares that make up a QR code). This is in order to have nicer vector output than simply making a bunch of rects for each module.

Long story short, my outline-tracing code works - BUT ONLY if I make sure to call NSLog in a specific place! If I remove the NSLog-call, the code loops! I'm literally doing nothing but logging. And it doesn't matter what I log; I just have to call NSLog or things break.

The tracing algorithm is simple enough: Go clockwise around the shape of connected modules. When you hit a corner, turn right until you're back to following the outline of the shape. Stop when you reach the starting point again. The shape can have two modules that share a corner-point. The tracing-loop will thus hit that point twice. This is expected, and the code handles it correctly - if I call NSLog.

Otherwise, the code will say that a certain point is a corner the first time it sees it, and not a corner the second time, which causes the tracing to loop around. Detecting if something's a corner-point is not dependent on anything except the x and the y coordinates of the point and an array of module objects - but neither the modules nor the array changes while the tracing is going on, so given the same x,y you should always get the same result. And it does – if I call NSLog.

Without NSLog, the coordinates – e.g. (10,9) – is corner on moment, and a moment later (10,9) is suddenly not a identified as a corner. But with an NSLog-call, (10,9) is correctly seen as a corner-point every time.

Again: I change absolutely nothing; I just log something - anything! And suddenly it works. It's like it's saying that 2 == 2 is true or false, unless I tell it to log 2 and 2, in which case 2 == 2 is always true, as it should be.

Here's the flaky code. It's hard to understand out of context, but there's a lot 开发者_如何学Pythonof context, so I hope this is enough. Everything is integers (no fuzzy floating point values).

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

If anyone can tell me why NSLog can make code work (or rather: Why not using NSLog makes working code break), I'd be happy to hear it! I hope someone can make sense of it.


Make sure cornerAtX:Y: always returns something—i.e., that there's no code path that fails to return a value.

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.


There's not much to go on here, but I'd guess that it's either an uninitialized variable or some sort of memory stomping. NSLog probably uses both stack and heap memory, so it could affect those.


Have you tried replacing NSLog with some other meaningless operation? If that will also work then I suppose problem is linked to [self cornerAtX: x Y: y]. Another possibility is that the problem is time-related. NSLog takes time to execute, so if QR code is loaded in another thread you can see this kind of behavior.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号