Pet Bugs II - Debugger War Stories
AlphaHelix queries: "A few weeks back there was an article on Pet Bugs, where people were asked about their favorite bugs. I have a different sort of question: what was your greatest debugging challenge? I've been debugging for a long time, from analog circuits all the way up to multi-kLOC multithreaded servers, and I have some pretty grisly war stories, like the time I debugged a problem in a third-party DLL in machine code because the client didn't have the source for it (yay open source.) What was your greatest debugging triumph?" The first time Slashdot did this it was more about bugs that you had encountered (and may not have solved), this one is about bugs in your own projects code and the trials and tribulations you had to go thru to get them fixed.
Now if you used constants instead of free strings you would have been ok....
static final String ANYTHING = "anything;
String x = ANYTHING;
if (x == ANYGHING) {
--Shemnon
Never trust M$? I'm sorry but it's clearly documented that the asserts are stripped from the release code. The macro to use for code you want to check in debug mode but still execute in release mode is VERIFY()
I'm no fan of Microsoft, but it's a bit easy to blame them for your own mistakes.
True warriors use the Klingon Google
I got stung by that on a Friday before a long weekend in 1984 or 1985. A dirty INT21 hook I was applying to DOS worked on ATs but not on XTs (or was it the other way around?). I had set up a structure on the stack and needed to pass its address to a higher language (prolly K&R C) routine, so PUSH SP seamed like the right thing to do.
Hardly a complex bug, but one where it is non-obvious that a 286 is not a superset of an 86.
Then there was the time I had to download a patch to over a thousand embedded controllers spread over a whole country whose problem was that downloading didn't work.... a truck roll to wach one was not an option. But, that's another story (bootstrapping the fix was horrendously more complex that finding the bug).
You could've hired me.
Good books, MS tools are weird mainly because I like my commandline a bit too much, but they publish some damn fine books about programming.
This is also a case of found easily by reading the output of gcc -E, you best friend when debugging code that has macro's anywhere near it.
I had never changed a flag that said I wanted it to strip them, so I assumed it wouldn't. Never trust M$
I hate to post a flame, but RTFM. On every compiler or tool you ever use, spend several days reading the manual and all associated docs you can find. Knowing how the compiler works, and how all the tools work is a hallmark of all the finest programmers I know. I used VC++ a handful of times 5 year ago, and I could have told you the asserts were stripped in from release mode. All you have to do is look at the full list of options it puts on the command line. That's relatively easy to find in the menuing system on VC 4.0 (the only version I used). The -DNDEBUG=1 flag turns off asserts.
Kirby
PS: Other then the keyboard and mouse I use, I haven't used a Microsoft product on a daily basis in years. It's about craftsmanship, and knowing your tools.
Take a look at VeriSoft, "a tool for software developers and testers of concurrent/reactive/real-time systems."
http://www.bell-labs.com/project/verisoft/
For those working in the comfy Java world, there's JProbe Threadalyzer . It can detect deadlocks, race-conditions, and other such niceties, and display them visually.
The ocean parts and the meteors come down
Laid out in amber, baby.
Java does _not_ guarantee that. It does guarantee that for the special case of a = "hello", b = a, then b == a.
;
Once you realise that Strings are Objects, all Objects are by reference (essentially any variable that is a subtype of Object is a pointer^H^Hreference), it makes perfect sense. == is a reference comparison, = is a reference assignment - so a and b point to the same string object.
This also has implications for function calls. Java is NOT a pass-by-reference language, but a pass-reference-by-value. For the most part, these are effectively the same thing, with one major difference. If I
baz () {
bar = "hello"
foo(bar);
[more code]...;
}
in java , the call to the foo method CANNOT change bar to point to a different object in the enclosing scope [more code] in baz(), but it can modify the object bar points to. In a true pass-by-reference language, foo could change bar to point to a different object, and the change would afffect [more code] i.e. it can modify bar itself...
This is a subtle distinction, and one that can catch people out in Java and Lisp.