Sign in to follow this  
BS-er

Undebuggable bugs

Recommended Posts

BS-er    181
I'm using Visual C++ 2005 Express. I seem to be running into a class of bugs that I can't debug. The problem is that everything always runs fine when the program is launched from Visual C++ using the green "Start debugging" button, but I get crashes when running the program standalone. I know my start paths are correct, so from my perspective the programs are launching in an identical manner. I'm sure the IDE does something different when launching so that the program can be halted etc., but it's confusing why that would mask the bug that occurs when launching standalone. It's complicated by the fact that I'm using freeware libraries. I'm able to determine that adding this call or that causes the crash, but that's no major help. I need to call those functions! It's a very exasperating problem. Heck if I could just find out what the IDE does that keeps the bugs from happening, I'd build it into my code! Anyone experience similar issues? I'd be greatful for any suggestions that may clear this up. [Edited by - BS-er on November 27, 2006 7:14:27 PM]

Share this post


Link to post
Share on other sites
romer    323
The first thing I typically do is try stepping through a debugger in order to get a feel for what values are being passed to and returned from functions while program execution, but since you say running from within VC++ seems to make it run just fine, you'll have to subscribe to an equivalent form of the printf school of debugging. If you have some logging mechanism in place, just start adding debug log messages... log things like functions being called, parameters passed to functions, return values returned from functions (especially library calls... usually this can give you some indication what to look more closely at). Granted putting in debug log messages will change the runtime behavior of your program, it's still better than nothing (unless of course it alters the runtime behaviour in such a way that the bug goes away... those are particularly nasty bugs to catch). One other thing you may want to try, and I haven't done this so I'm not too keen on how its done, is run the game and attach a remote debugger to the instance of your game. You can then set watchpoints and/or breakpoints, which may or may not give you some idea of what's going wrong. Without anymore specific details on the nature of your bug and whether it consistently happens, it is hard to give anymore specific or helpful advice.

Share this post


Link to post
Share on other sites
DvDmanDT    1941
In my experience, it's one of these:
1. The debugger initializes values to some non-zero value, while the release one might not..
2. The debugger is slower, meaning the program runs slower, and takes longer to start. Right now I just can't figure out the scenario when I ran into this, but I do know it has happend.. Especially when dealing with threads this might happend (does any of your freeware libraries use threads?).

Share this post


Link to post
Share on other sites
Muhammad Haggag    1358
Why don't you attach the debugger to the program after the crash and see where it crashed? Actually, Windows should give you the option to "Debug" a crashed program if you have a debugger installed/registered.

Also, I typically use a crash reporting tool like that of wxWidgets, or the stand-alone XCrashReport. With such a tool, you can use the crash (EIP) address generated to find out exactly where the program crashed.

Share this post


Link to post
Share on other sites
Armand    164
All so far are great and wonderful suggestions.

1 very low tech one is an attomic log to file function.
Then us a Macro that uses said function to print line number and file to said file.

once you zero in on the function and the line causeing the crash, you can use the log function to find out what is roughtly going on.

Macro I generally use is BFDB. It stands for Brute Force DeBugging.
It will make your app slower, so dosn't help in timming issue bugs. But it will work run in release mode.

Once th bugg is squished, its easy to either do a seach and replace, or just remove the macro body.

Share this post


Link to post
Share on other sites
yapposai    410
In a recent experience debug vs release crashes usually happens when I forget to
initialize pointers to NULL during declaration then having something like
 
If (ptr!=NULL) delete ptr;
ptr = new something;


during debug, the pointers are initialized to NULL but not during
release, causing the delete to crash the program.

Share this post


Link to post
Share on other sites
Zahlman    1682
I find it's easier to adopt good practices of the sort that make this class of bugs vanishingly rare. (This includes a lot of mostly simple things like using standard library containers and have specific idioms for using for-loops, declaring variables in a proper scope and near first use and initializing them with their first value; the occasional Boost widget; applying YAGNI - probably one of the most common sources of problems is needlessly making containers of pointers-to-object where containers of objects would suffice; refactoring the code to remove redundancy; etc. etc.)

Share this post


Link to post
Share on other sites
iMalc    2466
Quote:
Original post by Zahlman
I find it's easier to adopt good practices of the sort that make this class of bugs vanishingly rare. (This includes a lot of mostly simple things like using standard library containers and have specific idioms for using for-loops, declaring variables in a proper scope and near first use and initializing them with their first value; the occasional Boost widget; applying YAGNI - probably one of the most common sources of problems is needlessly making containers of pointers-to-object where containers of objects would suffice; refactoring the code to remove redundancy; etc. etc.)
You've replicated my thoughts exactly. Isn't hindsight wonderful?![smile]

But I would certainly try attaching the debugger when it crashes if he doesn't have time for a rewrite.[grin]

Share this post


Link to post
Share on other sites
Evil Steve    2017
I just want to point out that the IDE does not initialise values to anything. The compiler will initialise values to recognisable, non-null values in debug builds only. In release builds, the value of uninitialised varaibles is undefined, and depends on things like what was left on the stack by the last function called, what was in the area of memory you got before you got it, the phases of the moon, etc.
A release build running from the IDE should behave exactly like a release build running from explorer as far as code goes.

The only thing the IDE should do differently is set the current working directory. As a test, you could try changing the linker settings so your executable is placed in the project directory (Where the IDE sets the current working directory to), and run it from the IDE and from explorer.

As Zahlman said, the best protection against this sort of thing is making your code as bullet-proof as possible. If your code crashes near startup, logging will probably help you find where the code is crashing, and if it's something like a pointer dereference then you can also log the value of the pointer to make sure it's valid (Not null, or some other weird value)

Share this post


Link to post
Share on other sites
BS-er    181
Quote:
The only thing the IDE should do differently is set the current working directory.

Something is different, even when launching the exact same executable. When launched via VC++ "Start debug", the memory used by the executable is slightly more.

It's clear to me that launching using the VC++ "Start debug" causes execution to differ in some small manner. As I said earlier, everything is set up to start in the correct directory. I've checked for the basic blunders, like am I runnning different EXEs etc. everything checks out.

Quote:
Original post by alunharford
Buy/Beg/Borrow a system with VS Pro on it. Then you can debug the program when it crashes.

Will Visual Studio standard edition allow that as well?

[Edited by - BS-er on November 27, 2006 8:50:56 PM]

Share this post


Link to post
Share on other sites
hplus0603    11347
Quote:
Original post by Evil Steve
The compiler will initialise values to recognisable, non-null values in debug builds only.


That's not the only thing that is different. The standard memory allocators will detect that a debugger is attached, and initialize freshly allocated heap memory to a debug pattern. They won't do this when the debugger is not attached. This has nothing to do with debug/release mode compiles. It's being "helpful" that way.

The only way to get this is to run until you crash, and THEN attach with the debugger.

Share this post


Link to post
Share on other sites
Evil Steve    2017
Quote:
Original post by hplus0603
Quote:
Original post by Evil Steve
The compiler will initialise values to recognisable, non-null values in debug builds only.


That's not the only thing that is different. The standard memory allocators will detect that a debugger is attached, and initialize freshly allocated heap memory to a debug pattern. They won't do this when the debugger is not attached. This has nothing to do with debug/release mode compiles. It's being "helpful" that way.

The only way to get this is to run until you crash, and THEN attach with the debugger.
Interesting. I thought it was the code that's compiled into the executable that intitialises the memory rather than the IDE or something initialising it before handing it over to the executable...

Share this post


Link to post
Share on other sites
BS-er    181
I wonder if there is a way to investigate by using the registers reported at crash time, along with the map file.

Also I wonder if the crash is occuring in a freeware DLL, can I at least detect that fact, even if I can't zero in on the exact function?

Share this post


Link to post
Share on other sites
BS-er    181
Halleluyah! I fixed the problem without ever figuring out the real root cause! I don't know why this worked! In the Visual C++ Express, project properties, I switched the Runtime Library setting from "Multi-threaded DLL (/MD)" to "Multi-threaded (/MT)". That did it!

A whole slew of problems disappeared when I did that, all of which occurred only when running the program standalone, not through the IDE. I went back and enabled a whole bunch of calls that just seemed to break my program when using "Multi-threaded DLL (/MD)".

Now the world makes sense again! I can sleep at night! This makes me reasonably sure that I wasn't doing anything wrong (unless it's the wrong thing to use the Multi-threaded DLL).

On the surface I can't see why this makes a difference, unless I dare say that there is maybe a bug in the Windows Multi-threaded DLL.

I based my project off of the Ogre graphics engine samples, which all use the /MD option. Maybe the goal was to make very small EXEs, but think I can live with a hundred or so extra KB in my program.

If I need multithreaded, it's /MT from now on!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this