Solved

Program hangs- debugging question

Posted on 2011-09-17
13
697 Views
Last Modified: 2013-12-14
Hi experts, I have a program that hangs in release mode intermittently (always after doing something particular).  What are my options to find the problem, other than analyzing the code?

Is there something that can tell me which handle is being waited on in a release build from a non-developer machine (which I have admin access to)?

Many thanks!
Mike
0
Comment
Question by:thready
  • 4
  • 3
  • 3
  • +2
13 Comments
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 36553664
You could build in some logging information so that what is executed with what values gets written to a txt file for example.


Does it ever hang in debug build?  With Visual Studio a DEBUG build typically initialises variables to default values, a RELEASE build does not - the values it uses are just what happened to be at that memory location.  The result is often an intermittent failure that is not reproducible in a release build whereas the debug build runs 'perfectly'.
0
 
LVL 1

Author Comment

by:thready
ID: 36553710
Thanks Andy, I was hoping for an answer involving windbg or maybe process hacker or something like that...
0
 
LVL 28

Accepted Solution

by:
pepr earned 188 total points
ID: 36554883
You may be interested in post-mortem debugging. Search for the minidump -- the function 'MiniDumpWriteDump()'.  The key idea is that you can obtain the .pdb file for the release version of your .exe during the compilation.  Then you can use some functions in your code to write so called minidump file.  When the minidump file is put together with the original sources and with the .pdb file, you can see the sources and content of variables in the debugger as if you were debugging it just now.

There is a more difficult problem with capturing the stack when exception happens.  However it can also be solved.  I do not have my sources in hand now, but I can post them later.  If you can see the PAQ articles, have a look at http:Q_23310705.html, http:Q_23304126.html, ...

I will try to find more, but it is some time ago...  I did use it for ATL/WTL (no MFC) application, but it was the native one and it should be similar in your case.
0
 
LVL 40

Assisted Solution

by:evilrix
evilrix earned 125 total points
ID: 36555176
Hey Mike. Why not just attached Visual Studio's debugger to the process and debug it like that?
http://msdn.microsoft.com/en-us/library/c6wf8e4z.aspx

Providing you have the PDB files you should have no problem's other than because the code will be optimised (as it's a release build) the source code lines may not match up exactly with the process has hung so you may need to look at the disassembly to be sure of what you're looking at.
0
 
LVL 32

Assisted Solution

by:sarabande
sarabande earned 187 total points
ID: 36559196
i don't know for vs2010 and for managed c++, but all other versions of visual studio you can't debug a release built executable using the pdb (program database) of a debug version. so the best you can get when running the release version with the debugger or attach the ruuning process to debugger is assembler code and a stack pointing to addresses of the executable modules (exe and dlls).

i was used to add log messages at begin and exit of functions similar to that Andy had suggested above.

void someclass::afunction()
{
#ifdef TRACE_LOG   
tracelog("someclass::afunction begins");
#endif

...
#ifdef TRACE_LOG   
tracelog("someclass::afunction final exit");
#endif
}

Open in new window


the macro TRACE_LOG and the tracelog function could be defined in some common header. the tracelog function always should open and close the logfile such that you can find the last function called by the missing exit trace.  then you could narrow down the problem by adding more trace logs.

Sara


 
0
 
LVL 40

Assisted Solution

by:evilrix
evilrix earned 125 total points
ID: 36559223
>> you can't debug a release built executable using the pdb (program database) of a debug version
You can build symbol files with a release build -- that works just fine.
0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 32

Assisted Solution

by:sarabande
sarabande earned 187 total points
ID: 36559417
i tried such a release pdb only containing symbols recently for a issue when showing up a jpg image in a dialog. the issue was happening on vista only. it doesn't allow me to set breakpoints nor shows a useful stack. i had to produce a division by zero to get a stack at all at a suspicious statement. that all was little practical and i returned to more old-fashioned methods, such as analyzing error conditions, logging contents of variables, checking project properties. the last finally lets me find the reason where one dll was built with /MT and not with /MD switch like all others.

Sara



0
 
LVL 28

Expert Comment

by:pepr
ID: 36559454
@thready: Please, describe better the situation when the "program hangs". Does it crash or only stop to work?  For the crash that cannot be simulated easily in debugger, the minidump is the answer.  For the case when the program does not crash, the evilrix's suggestion to attach the running process to the Visual Studio debugger may be the answer.

Are you using threads?  If yes, then it can be caused by a deadloc (http://en.wikipedia.org/wiki/Deadlock) or a starvation problem (http://en.wikipedia.org/wiki/Resource_starvation) and it can be difficult to find the reason without analysing deeply the code.  
0
 
LVL 1

Author Comment

by:thready
ID: 36560346
Thank you very much for all your answers!  To be more precise, there is an error that says "Application MFC bla.exe has stopped working.  A problem caused the program to stop working correctly.  Windows will close the program and notify you if a solution is available".  Looks like an exception occured.

I am now re-going through all your comments with a fine-tooth comb!

Thanks again!
Mike
0
 
LVL 32

Assisted Solution

by:sarabande
sarabande earned 187 total points
ID: 36560450
this kind of crash mostly comes when a null pointer or invalid pointer is used. the error then would be 0xC0000005. if you run the application from visual studio with f5 the debugger should show you the exception and allow to retry what should step into some code or assembler where you could examine the call stack. because of release version the call stack will have som runtime dll or mfcdll at the topmost positions what doesn' t help you much. you can improve the result by setting the exception to break immediately when thrown. that can be done at menu debug - exceptions and checking the right exception code accordingly. for access violation you find the code below win32 exceptions. then run the app again and when crashing you'll get a better stack which could give you the function name where the exception was created.

Sara
0
 
LVL 28

Assisted Solution

by:pepr
pepr earned 188 total points
ID: 36566324
To add, this kind of "general error" is usually reported by the runtime.  You can catch it earlier via your own construct try / catch inside the main body of your application.  The low-level errors can be converted to C++ standard exceptions.  Then you can add the code that saves the stack and the content of the variables (minidump).  The result can be "debugged" later -- very useful if you cannot simulate the problem using the debugger or when the situation happens occasionally at the customer computer.
0
 
LVL 28

Assisted Solution

by:pepr
pepr earned 188 total points
ID: 36574127
For the case you are interested in the post-mortem debugging, here is the working code that shows how to do the minidump.  It is attached with the Visual Studio 2005 project.  

My problem with the minidump was that the plain simple code that calls the functions to create a minidump was not able to show the stack when the exception happened.  The reason was that the stack was destroyed during "stack unwinding", i.e. during the recovery from the exception.

Part of the stack unwinding in the code generated by the Microsoft compiler is calling of destructors of objects that were created along the path.  This fact was used to create the object of the MiniDumper class at the beginning of the "try" block.  The minidumper object is disabled just before the end of the try block.  This way the minidump function is called when needed.  The cost is that you have to explicitly use the minidumper object.

Here is the code of the example (main.cpp):

#include <iostream>
#include <stdexcept>
#include "MiniDump.h"

using namespace std;


void f1()
{
    cout << "f1() throw\n";
    throw runtime_error("runtime_error thrown in f1()");
}

void f2()
{
    cout << "f2() start\n";
    f1();
    cout << "f2() return\n";
}

void f3()
{
    cout << "f3() start\n";
    f2();
    cout << "f3() return\n";
}

void f4()
{
    cout << "f4() start\n";
    f3();
    cout << "f4() return\n";
}


int main()
{
    cout << "main() start\n";
    try
    {   MiniDumper md;
        f4();
        md.Disable();
    }
    catch (const runtime_error & e)
    {
        cout << "runtime error: " << e.what() << "\n";
    }
    cout << "main() return\n";
    return 0;
}

Open in new window


When running, it prints:

d:\Tutorial\MiniDump04BeforeUnwinding\Debug>MiniDump.exe
main() start
f4() start
f3() start
f2() start
f1() throw
runtime error: runtime_error thrown in f1()
main() return

Open in new window


and it creates the minidump.dmp file that captures the situation.  It's size is about 15 KB in the case.  Then you can launch the Visual Studio, from the main menu you choose File -- Open -- Project/Solution..., selec the minidump.dmp and OK.  Then you press F5 (i.e. Run) -- as if you started the application.  It stops with the warning window "Unhandled exception..." and you press Break.  Then you can see the stack in IDE like this:


Stack in the IDE
Again, this method is suitable when normal debugging is not possible.
MinidumpWithStackBeforeUnwinding.zip
0
 
LVL 1

Author Closing Comment

by:thready
ID: 36919120
Again a big thanks to everyone on this- all these answers are excellent, so I still need to reward points!  However, I found my problem by running in debug mode but I need to turn on "Win32 Exceptions" Debug | Exceptions menu.
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
haveThree challenge 22 103
MaxSpan challenge 9 68
Best book to learn C++ 4 55
eclipse package explorer vs project explorer view 2 34
Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
Introduction: The undo support, implementing a stack. Continuing from the eigth article about sudoku.   We need a mechanism to keep track of the digits entered so as to implement an undo mechanism.  This should be a ‘Last In First Out’ collec…
The viewer will learn how to use NetBeans IDE 8.0 for Windows to connect to a MySQL database. Open Services Panel: Create a new connection using New Connection Wizard: Create a test database called eetutorial: Create a new test tabel called ee…
The viewer will learn how to use and create keystrokes in Netbeans IDE 8.0 for Windows.

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now