Unhandled exception - Different under debugger and non-debugger

R

RalphTheExpert

I'm getting different behavior if my code is running under the
debugger or not.

I have modified Winmain to look like this:

// Copyright (C) 2002 Microsoft Corporation
// All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER
// EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
WARRANTIES OF
// MERCHANTIBILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.

// Requires the Trial or Release version of Visual Studio .NET
Professional (or greater).

#include "stdafx.h"
#include "frmMain.h"
#include "MyException.h"

using namespace VCNET;

[System::STAThreadAttribute]
void __stdcall WinMain()
{
try
{
Application::Run(new frmMain());
}
catch (MyException* pMyException)
{
// Show the exception to the user.
MessageBox::Show
(
System::String::Concat
(
MyException->ShowFullMessage(),
S"\r\n\r\n",
S"Internal failure. Program terminates."
),
S"Internal failure. Program terminates.",
MessageBoxButtons::OK,
MessageBoxIcon::Error
);
}
}


In a button handler I throw a MyException.

Under the debugger, the exception is caught in WinMain and a proper
dialog box is displayed.

If I run the executable (either Release or Debugger builds) then the
exception is not caught and the system displays an unhandled exception
message. The unhandled message displays the proper information.stored
in the MyException object.

Admittedly, the exception is being thrown from a function thirty levels
of procedure call between the function and WinMain() through a bunch of
system dlls.

Nonetheless, I would not expect different behavior if the program is
running under the debugger and without the debugger.
 
P

Peter Oliphant

I have found if you change:

int __stdcall WinMain(void)

as the 'main' call format to:

int _tmain(void)

that the exception goes away for me. BUT, this brings up the black Console
screen, which I need to eliminate. So I have the problem (in my case)
half-solved... : )

[==P==]
 
R

RalphTheExpert

My guess is that the console screen comes up because you have specified
that the linker option, subsystem, is console rather than than windows.

If the program is console then the envirnoment is much simpler and
there are likely far fewer dlls between a throw and the catch.


I vaguely remember haveing the same problem in VC 6. If my memory is
correct, it was bad to attempt to do a throw from inside of a message
pump to outside of one.


I know fairly little of the internals of MC++ in a /subsystem:windows
environment. I'm not even sure if there is a message pump.

Nonetheless, I'd sure like to know if it is legal to do a throw from
inside a message handler all the way out to WinMain.
 
P

Peter Oliphant

I checked, and it was at 'Not Set'. When I set it to /SUBSYSTEM:WINDOWS it
will give me a compiler error unless I use int __stdcall WinMain(void) as
the 'main' call to the application, in which case it doesn't bring up the
Console but does exit with an exception error. If I set it to
/SUBSYSTEM::CONSOLE I get a compiler error unless I use int _tmain(void) as
the 'main' call to the application, in which case it brings up the Console
and there is no exception error on exit.

Thus, it behaves no different than if I left it to 'Not Set' and just
changed the form of the 'main' call. I can think of no good reason that a
program should produce an exception error (you know, the kind that brings up
the 'do you want to send this problem to MS for analysis?' dialog box)
UNLESS its uses a Console. This probably means the problem isn't in my
application code, but in some setup of the project. Since this didn't happen
in 2003, how in hell am I suppose to find out what is causing the exception
(the info it spits out is of no apparent help, it just says it got an
exception error and exits with code: -1073740791 (0xc0000409). Oh goody,
isn't that helpful? ; )

One thought. I allowed 2005 to convert my application from 2003 to 2005.
When I did this with a project from 2002 to 2003 it turned out the
conversion was not entirely successful, and 3 weeks later I ran into a bug
that could only be fixed by opening up a new 2003 project and copying the
source over form the previous project (it kept telling me I was using an
out-dated version in the Linker, but the interesting part is that this
warning only started happening weeks after I did the conversion, during
which time I did EXTENSIVE changes and additions to the code). Is it
possible the 2003 to 2005 conversion also has problems?

[==P==]
 
C

Carl Daniel [VC++ MVP]

RalphTheExpert said:
I'm getting different behavior if my code is running under the
debugger or not.

I have modified Winmain to look like this:

[snipped code]
In a button handler I throw a MyException.

There's your problem. It's undefined whether an event that's raised in a
window message handler will propagate out to the message loop (or the caller
of the message loop in your case).
Under the debugger, the exception is caught in WinMain and a proper
dialog box is displayed.

If I run the executable (either Release or Debugger builds) then the
exception is not caught and the system displays an unhandled exception
message. The unhandled message displays the proper information.stored
in the MyException object.

Admittedly, the exception is being thrown from a function thirty levels
of procedure call between the function and WinMain() through a bunch of
system dlls.

Nonetheless, I would not expect different behavior if the program is
running under the debugger and without the debugger.

The debugger is very intimately involved in propagation and handling of
exception when attached, so I'm not too surprised that there's a difference
in behavior.

-cd
 
R

RalphTheExpert

Carl:

As I had written in another eMail: "I vaguely remember haveing the same
problem in VC 6. If my memory is correct, it was bad to attempt to do a
throw from inside of a message pump to outside of one."

I'd like to ask two related questions.

(1) Why is the behavior undefined and where is it written that it is
undefined?

(2) What's the proper way to take care of an exception in a message
handler? How can one propagate the error out of a message handler?
 
C

Carl Daniel [VC++ MVP]

RalphTheExpert said:
Carl:

As I had written in another eMail: "I vaguely remember haveing the
same problem in VC 6. If my memory is correct, it was bad to attempt
to do a throw from inside of a message pump to outside of one."

I'd like to ask two related questions.

(1) Why is the behavior undefined and where is it written that it is
undefined?

I wish I had a good answer. I got that answer in the kernel group, from
Ivan Bruglio of Microsoft. It's basically just not supported by
User32.dll - it might work, it might not.
(2) What's the proper way to take care of an exception in a message
handler? How can one propagate the error out of a message handler?

I would think the only fully sanitary, guaranteed to work way would be to
either terminate the program from inside the handler, or intern the
exception in an object and pass (a pointer to) that object through a WM_APP
window message where your message loop can unwrap it and re-throw or
otherwise handle the exception.

-cd
 
O

Oleg Starodumov

I'm getting different behavior if my code is running under the
debugger or not.
...
In a button handler I throw a MyException.

Under the debugger, the exception is caught in WinMain and a proper
dialog box is displayed.

If I run the executable (either Release or Debugger builds) then the
exception is not caught and the system displays an unhandled exception
message. The unhandled message displays the proper information.stored
in the MyException object.

The difference in behavior is because WinForms uses different window procedures
when running under debugger and without debugger. The one used under debugger
allows exceptions to propagate, the one used without debugger catches and reports
them. It can be changed in the application's .config file:
http://support.microsoft.com/default.aspx?scid=kb;en-us;836674

Regards,
Oleg
[VC++ MVP]
 
O

Oleg Starodumov

I wish I had a good answer. I got that answer in the kernel group, from
Ivan Bruglio of Microsoft. It's basically just not supported by
User32.dll - it might work, it might not.

I believe it applies to native C++ exceptions, and the problem is that these exceptions
are described with a set of data structures, which are (can be) specific
to a particular version of CRT. When a module throws a C++ exception and
another module, linked with a different version of CRT, tries to analyze its decription
(to determine its type and decide whether it should be handled), the difference
in the exception description formats can lead to unpredictable results.

Regards,
Oleg
 
R

RalphTheExpert

Oleg and Carl:

I am continuing this thread in a new thread:

BUG: An exception does not propagate correctly to the calling function
in a Windows Forms application project in Visual Studio .NET

Ralph Shnelvar
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top