I am writing a C++ program in MS Visual Studio and the problem I'm having is that my program gives the correct output when I'm running it under debugging mode, but when I just run it without debugging, the output changes.
I can't think of anything that could cause something like this? Any ideas what's going on?
What is the difference behind the scene between just running the program vs. debbugging it?
Since it only doesn't work when I'm not using the debbugger, I really don't know how to appraoch the problem.
I would really appreciate your help.
Sorry but I can offer only general points from the information you provided.
First, obviously when running under the debugger you use a debug build, but when not running under the debugger do you use the same debug build or have you built using a release build?
Also if running a debug build without the debugger do you do this from within Visual Studio or from outside - e.g. from a command shell? If the latter then ensure you are executing the executable you intend. By default Visual Studio places a debug build executable in the Debug directory within the project directory.
If running a release build then the code compiled may well differ from that compiled for a debug build as the defined pre-processor macros generally differ - so for example debug only code blocks are omitted. Pay special note of this if you use the assert macros - in a release build they expand to nothing so doing actual work in an assert is a bad idea! For example:
bool initialise(); // function defined elsewhere
assert( initialise() );
In a debug build initialise is called. In a release build it is not. A better way to achieve the above would be:
bool isInitialised( initialise() );
assert( isInitialised );
With luck an optimised build will remove isInitialised if this is its only use. In this particular case I would think it is likely that failure to initialise something may be of the class of errors that require some form of error handling - such as printing or logging an error message and cleanly shutting down the process, and not just an assertion which should really be used to detect such things as breaches of pre and post conditions and invariant conditions which infer programming errors rather than external problems such as bad input or lack of resources.
Which brings us onto the other main difference between a debug build and a release build - a release built usually takes advantage of code optimisations offered by the compiler and this obviously changes the object produced - in particular the instruction sequences. Occasionally these optimisations can cause problems and some optimisations can only be used safely if your code meets certain criteria.
Other things that happen under a debug build are that heap memory blocks are assigned different values depending on their state: allocated but un-initialised, de-allocated etc. Also the debug heap leaves addition memory at the end of each block and check to see if you overrun the block you were allocated.
If you are merely running the same debug build not under the debugger and you get different results then the reasons are more difficult to see. The code is the same, unless, as mentioned above, you are accidentally running the wrong executable. The only thing that springs to mind involves timing issues - and generally these only show when many things are happening and you break into the code (e.g. by setting a break point which is then reached) - thus disrupting the timing sequence in relation to other threads and / or processes. Another similar issue would be the switching of focus back to the debugger from the application when reaching a break point. This can disrupt the message flow for Windows programs, as well as things such as painting the application window - a problem when debugging window painting code.
Other things to watch are the current path and user input. Running a program from different places causes the default path to be different - so searching for files may be affected. Running under the debugger, again when breaking the code execution, will disrupt the input focus so may miss enter some data - however I would have thought in this case the problem would be when running under the debugger and not the other way around.
Other than that the debugger should be transparent to the code execution and generally it is unless you break into the code or set watch points or some such. However the debugger is still there so in some cases it may have an effect on the execution of a program. However that program is most likely only working by accident in such cases - there is something wrong with the code and it just happens _not_ to happen when running under the debugger.
However without knowing what the code is that is causing the problems I cannot give more specific advice - and please do not post me reams and reams of code - I simply do _not_ have the time to read it.
There are some ways to approach such problems. The simplest is the time - honoured tradition of inserting (temporary) diagnostic trace output. If you are using the MFC you can use the TRACE macro, or if using the ATL there is the ATLTRACE macros. These work like the C standard library function printf, but place their output in the VS output window:
TRACE("Function xxx entered\n");
TRACE("x initialised, x=%d\n", x);
The plus point with such macros is that like assertions they are removed from release builds.
Of course you can always just add good old C or C++ output to your code, providing you have a stdout, stderr or file stream to write to:
std::cerr << "Function xxx entered\n";
std::cerr << "x initialised, x=" << x << "\n";
but then you would have to remove them when you have finished debugging the problem - so try to keep them localised in your code and make them easy to find - I often place such statements right against the left hand side - ignoring any indentation so it is obvious they are out of place. If they need to stay for a prolonged period then define a special pre-processor macro (e.g. in the debug build compiler pre-processor settings) for the debugging session and wrap such debugging code in conditional compilation blocks. So for this problem you might define a DEGUG_STRANGE pre-processor symbol and use it like so:
std::cerr << "Function xxx entered\n";
Building without DEGUG_STRANGE defined causes any code blocks within #ifdef DEGUG_STRANGE to be skipped over when the source file is pre-processed so they never get compiled. Also you can search for all such blocks and remove them when you are done.
Hope this helps a little.