Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Debugging and Other Tips & Tricks

Debugging and Other Tips & Tricks

Brian Kernighan famously quipped, "Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it."

That debugging is hard is a universal truth, however the unmanaged code we write as Cocoa developers does make our life somewhat more difficult. We can't always stand on the shoulders of @mikeash, @gparker & @bbum when we get a crash in objc_msgSend()!

Kernighan's second point is even more salient — while it may be tempting to write tricky code, it can become a debugging nightmare. If you anticipate the need to debug code while you're writing it, you'll be better off when you're tracking down yet another heisenbug.

In this talk I'll discuss the tools you can use to make debugging easier, and some techniques for ensuring you've not coded a rope long enough to hang yourself. You'll walk away with some extra arrows to your debugging quiver, and a better idea of how to write more debuggable code.

Nathan de Vries

September 28, 2011
Tweet

Other Decks in Programming

Transcript

  1. And other investigative tips & tricks Nathan de Vries Wielder

    of bits, bytes & all things nice. Debugging
  2. Debugging is twice as hard as writing the code in

    the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. — Brian W. Kernighan “ ”
  3. NSLog(@"Made it here, yay!"); #define ALog(format, ...) NSLog((@"%s [L%d] "

    format), \ __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__) #if DEBUG_LOGGING_ENABLED #define DLog(format, ...) ALog(format, ##__VA_ARGS__) #else #define DLog(...) #endif (gdb) print-object anObject <NDVObject: 0x4e89670> Beyond Rubber Ducking
  4. But it’s “Good enough!” • No, it’s not • Changing

    the code you’re debugging • Mostly suited to “passive” debugging • Requires recompilation • Non-performant on device • Noisy • Error prone (e.g. NSLog() is non-reentrant!)
  5. So, Specialised Tools! 1. Interactive debugging 2. Testing 3. Logging

    4. Network condition simulation 5. Network traffic debugging 6. UIKit animation hacking 7. View hierarchy inspection & manipulation
  6. Command Abbrev. Description continue c Continue until the next breakpoint

    step [count] s Single step the next [count] statements. Step into functions. next [count] n Single step the next [count] statements. Step over functions. finish p Execute the rest of the current function. Step out of the function. print expression p Print the value of an expression print-object obj po Print the value of [obj debugDescription]. set var = exp - Set a variable. e.g. set obj = (void *)[[NSObject alloc] init] call expression c Call a function. e.g. call NSLog(@”Can’t break the habit.”) jump line j Continue at a given line (or address). backtrace [count] bt Print a backtrace of [count] frames. return [expression] - Return the value of [expression] to the previous stack frame. There’s more than just po, you know?
  7. ...after debugging I knew where the defect was, but after

    squeezing I had a minimal unit test for the defect as well. That concise test is a handy by-product of the process. — Kent Beck Regression Testing & The Saff Squeeze http://www.threeriversinstitute.org/HitEmHighHitEmLow.html “ ”
  8. GHUnit • SenTestKit has, historically, been a path to madness!

    • Tests run as separate target • GUI & CLI runner • Selectively run & re-run tests • Setting a breakpoint doesn’t require a PHD • Supports asynchronous tests, runnable in parallel https://github.com/gabriel/gh-unit
  9. @interface CSAccountTests : CSTestCase @end @implementation CSAccountTests - (void)setUp {

    self.testAPI = ...; } - (void)tearDown { self.testAPI = nil; } - (void)testGetAPIKeyWithValidCredentials { [self testAsync:^{ self.testAPI.username = kCSTestsValidUsername; self.testAPI.password = kCSTestsValidPassword; [self.testAPI getAPIKey:^(NSString* APIKey){ [self notifyTestFinished]; GHAssertNotNil(APIKey, @"no API key returned"); GHAssertTrue([APIKey length] == 16, nil); } errorHandler:[self assertNoError]]; }]; }
  10. NSLogger LogMessage(@"example", 0, @"Example message"); LogData(@"example", 1, imageData); LogImageData(@"example", 2,

    width, height, imageData); LogMarker(@"Example marker"); • Indispensable drop-in NSLog() replacement • Log entry categorisation via tags & levels • Built-in image and data-type logging • Marker support • Fast data mining tool • Bonjour discovery over WIFI
  11. $ ipfw add pipe 1 ip from any to any

    in $ ipfw add pipe 2 ip from any to any out $ ipfw pipe 1 config delay 400ms bw 240Kbit/s plr 0.01 $ ipfw pipe 2 config delay 440ms bw 200Kbit/s plr 0.01 /Developer/Applications/Utilities/Network Link Conditioner/Network Link Conditioner.prefPane
  12. Charles Web Debugging Proxy • Inspect, modify, store, share &

    replay requests • Local content substitution • Bandwidth / latency simulation • Cache-related HTTP header stripping • Man-in-the-middle SSL support