|
Which of the three uses do you disagree with? The first use (catch(...) at the end of main) is only when every other remedial action has failed and the program's going to crash anyway. If you have other base exceptions or exceptions that aren't derived from std::exception feel free to add catches for them at the top level.
Another type is where something throws in a destructor. You can't let exceptions come out of a destructor, std::terminate will end up being called in most cases. So the program's going to crash - you might as well handle it and tell the user that something's gone wrong then bail out cleanly.
A final example is where you don't know where you're throwing. If you have a C interface there's no guarentee that something on the other side knows what to do with it. So catch the exception and translate it to an error code - even if the error code is "Buggered if I know what went wrong in here mate..." which should be translated by the caller into stick up an error message and bail out of the program.
One final point - you shouldn't need to manually clean up resources in the face of an exception. We're talking C++ here and not Java (and even then you've got finally , not catch( ... ) ). The general idiom with C++ is to handle cleanup of resources using RAII, don't do it manually 'cause you're bound to miss something.
Cheers,
Ash
|
|
|
|
|
On the issue of a catch (...) in main as follows (I also have objections on other grounds, but we'll address one issue at a time):
#include "stdafx.h"
#include <tchar.h>
#include <iostream>
#include <stdexcept>
using namespace std;
class MyException : public runtime_error
{
public:
MyException(const char *pMsg) : runtime_error(pMsg) {}
};
void SomeFunction()
{
throw MyException("SomeFunction()");
}
int _tmain(int argc, _TCHAR* argv[])
{
try
{
SomeFunction();
}
catch (...)
{
cerr << "Caught exception..." << endl;
}
return 0;
}
All the error information you get from the unexpected event is the following message:
Caught exception...
If the catch (...) is removed a crash dump is generated and the stack extracted from it (using WinDBG) looks as follows:
0:000> .ecxr
eax=00000000 ebx=0024f2d4 ecx=00000000 edx=0008dcd8 esi=770a030c edi=011915e3
eip=742dbb47 esp=0024f1e8 ebp=0024f214 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
msvcr90!terminate+0x33:
742dbb47 e879100100 call msvcr90!__SEH_epilog4 (742ecbc5)
0:000> kvn 1000
# ChildEBP RetAddr Args to Child
00 0024f214 0119161f 0024f2a4 77009d57 0024f2d4 msvcr90!terminate+0x33 (FPO: [Non-Fpo]) (CONV: cdecl) [f:\dd\vctools\crt_bld\self_x86\crt\prebuild\eh\hooks.cpp @ 130]
01 0024f21c 77009d57 0024f2d4 b21db5fb 00000000 Console!__CxxUnhandledExceptionFilter+0x3c (FPO: [Non-Fpo]) (CONV: stdcall) [f:\dd\vctools\crt_bld\self_x86\crt\prebuild\eh\unhandld.cpp @ 72]
02 0024f2a4 77b10727 0024f2d4 77b10604 00000000 kernel32!UnhandledExceptionFilter+0x127 (FPO: [SEH])
03 0024f2ac 77b10604 00000000 0024f894 77acc3d0 ntdll!__RtlUserThreadStart+0x62 (FPO: [SEH])
04 0024f2c0 77b104a9 00000000 00000000 00000000 ntdll!_EH4_CallFilterFunc+0x12 (FPO: [Uses EBP] [0,0,4])
05 0024f2e8 77af87b9 fffffffe 0024f884 0024f424 ntdll!_except_handler4+0x8e (FPO: [4,5,4])
06 0024f30c 77af878b 0024f3d4 0024f884 0024f424 ntdll!ExecuteHandler2+0x26
07 0024f3bc 77ab010f 0024f3d4 0024f424 0024f3d4 ntdll!ExecuteHandler+0x24
08 0024f3bc 772bb727 0024f3d4 0024f424 0024f3d4 ntdll!KiUserExceptionDispatcher+0xf (FPO: [2,0,0]) (CONTEXT @ 0024f424)
09 0024f75c 742ddbf9 e06d7363 00000001 00000003 KERNELBASE!RaiseException+0x58 (FPO: [4,20,0])
0a 0024f794 0119106a 0024f7b4 01192460 b21db00a msvcr90!_CxxThrowException+0x48 (FPO: [Non-Fpo]) (CONV: stdcall) [f:\dd\vctools\crt_bld\self_x86\crt\prebuild\eh\throw.cpp @ 161]
0b 0024f804 011912ca 00000001 005920e8 00591e00 Console!SomeFunction+0x65 (CONV: cdecl) [c:\users\stephen.hewitt\documents\visual studio 2008\projects\scratch\console\console.cpp @ 19]
0c 0024f848 76fe3677 7efde000 0024f894 77ad9d72 Console!__tmainCRTStartup+0x10f (FPO: [Non-Fpo]) (CONV: cdecl) [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 579]
0d 0024f854 77ad9d72 7efde000 72bf8284 00000000 kernel32!BaseThreadInitThunk+0xe (FPO: [1,0,0])
0e 0024f894 77ad9d45 01191412 7efde000 00000000 ntdll!__RtlUserThreadStart+0x70 (FPO: [SEH])
0f 0024f8ac 00000000 01191412 7efde000 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [2,2,0]))
This shows what went wrong and where. What's more, this information is sent to Microsoft and can be analysed by the software publisher using Microsoft's Windows Error Reporting[^] website. You get real crash data from real users as well as statistical information on the most common problems.
In short, a pretty message saying "oops" isn't as helpful — crashing is a feature.
Steve
|
|
|
|
|
thanks for the detailed reply but for a lay user, crash is just an act of cheating by the application. if a software crashes 2-3 times, I normally uninstall it (except the windows OS and ibm rational clearcase coz' i do not hv options in these 2 cases)
If one use catch all in main and then give some kind of error message to the user, that this module has failed. we're sorry. our chipmunks are running to solve your problem, then it is better.
and regarding your stack trace, yes it can be very helpful if you can get the log but I dont know much about it. I think there are ways using SEH to get stack trace etc.
anyway, you made a good point )
|
|
|
|
|
Sure, if it crashes frequently you ditch it. Nothing unusual about you so far. What do you do if it doesn't crash per se, but instead fails with a generic error message just as frequently? I suspect the same. I say let it crash, suck down the crash dumps and fix the problem.
Steve
|
|
|
|
|
yes, you are right but correct me if I am wrong. Windows 7 seems to be using lot of exception handling and displaying message about why it crashed with what error code. eg. in windows xp, if your explorer crashes, you get a message like "An unhandled win32 exception occured in explorer.exe".. but in windows 7, i hope you have observed it's different. they give you error message etc. You can argue that even information in latter case is not very helpful but in my experience, it is less annoying.
same is the case with world's best browser opera. whenever it crashes (once a year or two maybe.. to be honest, opera never crashed before v9. after that i think lot of advancements have made it complex, so it has started crashing once every 3 months or so), an option is provided to restart the browser, along with sending crash dump to opera where it is analyzed and the reason for crash is displayed to the user.
In nutshell, exception handling when done properly can make your application more polite and responsible. If you are not handling exceptions and your application crashes without a hint, how the user will know which dump files to send to which address and in fact, will they ever bother to do it themselves?
|
|
|
|
|
Windows Error Reporting[^] allows you to publish a solution for a particular stack (it classifies crashes). When you do this and a user gets that particular crash, they get the message you associated with it. This allows you to tell the user what's wrong and what to do about fixing it. The dumps are send automatically (the user has to agree). Sure you could use some custom error reporting framework as some products do, or you could just let it crash and use the one that comes with the OS.
Steve
|
|
|
|
|
yes, it is a good alternative. One of the requirements of using it is that "You must have administrative privileges on the machine you are using". That should not be a problem in majority of cases though.
second thing is it is "windows" specific. Exception handling is platform neutral.
third thing is I never send data to microsoft website. however, if any of my fav. app crashes, i do send the crash dump to them.
thanks for the info. btw.
|
|
|
|
|
theCPkid wrote: One of the requirements of using it is that "You must have administrative privileges on the machine you are using". That should not be a problem in majority of cases though.
I'm not sure what you're referring to here. The user doesn't need to have administrative privileges to submit a dump file.
theCPkid wrote: second thing is it is "windows" specific. Exception handling is platform neutral.
Yeah, Windows Error Reporting is certainly Windows specific. That said this message board is primarily about Windows. The general principle of crashing as close to the initiating fault still applies.
Steve
|
|
|
|
|
This is a complete strawman - the exception you're throwing is derived from std::exception so the first catch clause I wrote would have caught it.
|
|
|
|
|
Aescleal wrote: This is a complete strawman - the exception you're throwing is derived from std::exception so the first catch clause I wrote would have caught it.
You seem to be missing the point. The choice of exception was arbitrary, the point is that it's not expected. Sure the first catch in your code would have caught it, but there is no such beast in the code I posted. My code is different to yours; you seem to be misrepresenting my argument. Who's augment is the straw man? You asked me to elaborate on my position and I did: instead of the user getting a generic error message (of no use to anyone) I get a dump file. I prefer the latter.
Steve
|
|
|
|
|
Stephen Hewitt wrote: crashing is a feature.
and I provide that feature absolutely free with no hidden costs in all of my products.
|
|
|
|
|
One open source project whose author knows about try..catch blocks is this:
1. http://freshmeat.net/projects/ecasound[^]
check ecasound-2.7.1\ecasound-2.7.1\Documentation\programmers_guide\ecasound_programmers_guide.txt
(use of EH is very minimal here ut at least it exists)
I will add more projects as and when I find them... have installed a catch(...) for all future source code checks.
modified on Tuesday, June 29, 2010 9:21 AM
|
|
|
|
|
Hello all
I've implemented a class dervied from CRecordset.
this class gets the DB and sql query and retrives data.
everything was working fine, untill i've decided to delete the data directly from the DB.
when i'm running the same code, the class retrives the same data, although the data is erased.
what's the problem ??
CSpecificGraphsRS rsSpeGraphs(&m_db);
strQuery.Format("SELECT * FROM GRAPHS ORDER BY GRAPH_ID");
rsSpeGraphs.Open(CRecordset::snapshot, strQuery, CRecordset::none);
while (!rsSpeGraphs.IsEOF())
{
genGraphDisplay.strGraphId = rsSpeGraphs.m_GRAPH_ID;
}
|
|
|
|
|
Did you make sure your program is accessing the same database that you directly deleted data from? Sometimes multiple test databases are used and the wrong one may be modified, making you believe that the program is not working.
|
|
|
|
|
yes i did,
they access the same DB.
|
|
|
|
|
Are the records in the set truly deleted? Try:
while (! rsSpeGraphs.IsEOF())
{
if (rsSpeGraphs.IsDeleted())
TRACE(_T("Recod is deleted.\n"));
rsSpeGraphs.MoveNext();
}
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Man who follows car will be exhausted." - Confucius
|
|
|
|
|
HI,
What is pure virtual destructor?
what is the use of using pure virtual destructor ?
Thanks,
Krish.
|
|
|
|
|
See, for instance, the competitors...[^].
Personally, I think you should always use virtual destructors. No need to have pure virtual destructors (see [^]).
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
|
A pure virtual destructor is any destructor marked as virtual with = 0 after it's signature, e.g:
class T
{
public:
virtual ~T() = 0;
};
Making a destructor pure virtual means very little more than making the destructor virtual (and you do that to make sure the correct destructor is called when you delete an object through a base class pointer). The additional bit is that it means the derived class has to define it's own destructor and not rely on the base class one.
One additional wrinkle is that all pure virtual destructors have to have an implementation, unlike normal pure virtual member functions which don't have to have one.
Cheers,
Ash
|
|
|
|
|
Hi,
I have developed and application based on modeless dialogs (the view is a formview and the others are CDialog and I show and hide them as corresponds). But I have a problem because when a modeless dialog has the caption, the mainframe loses it and I cannot access to the menu and toolbar from acceleratos because they don't have the caption.
How could I keep always caption on the mainframe? Maybe all dialogs can be defined as formview?
Thank in advance
|
|
|
|
|
Don't make the dialog a child of your main window, set its parent window to NULL. In that way it will be a child of the desktop and will not take the focus from your main window.
It's time for a new signature.
|
|
|
|
|
Or you can leave it like child of your window and put return FALSE in OnInitDialogfunction
|
|
|
|
|
What?
It's time for a new signature.
|
|
|
|
|
Hi,
Thank you for your help, but unfortunately it didn't work.
I set:
BOOL CDlgListaPt::Create()
{
return CDialog::Create(CDlgListaPt::IDD);
this->SetParent(NULL);
}
and also tried in Oninitdialog method but the mainframe lose caption
my dialog is a popup non-modal dialog that is created from the view (what is a formview)
If I change the dialog style to child, the mainframe keeps caption but I cannot control de dialog.
The other solution returning false in oninitdialog it didn't work either.
Regards
|
|
|
|