How to ensure a statement be executed in C++? I mean if an exception is thrown before the statement then the statement most likely won't be excuted. For those statements to release the resource, for instance, close the files, it is really bad.
Printable View
How to ensure a statement be executed in C++? I mean if an exception is thrown before the statement then the statement most likely won't be excuted. For those statements to release the resource, for instance, close the files, it is really bad.
That is what try/catch is for :D
Sometimes it's necessary to call your cleanup code from the catch block.
Let me give an example,Quote:
Originally posted by TheCPUWizard
That is what try/catch is for :D
try
{
statement s1;
statement s2;
statement s3;
...
}
catch(someException e)
{
...
}
If statement s1 throws an exception, how do you ensure s3 be excuted? Thanks.
you should be catching your exceptions by constants reference.
try
{
statement s1;
statement s2;
statement s3;
...
}
catch(const someException& e)
{
...
}
Well...by putting it into the 'catch' block... :DQuote:
Originally posted by dullboy
If statement s1 throws an exception, how do you ensure s3 be excuted? Thanks.
No...serious, the first question would simply be why you want to execute statement s3 although statement s1 has failed? How can you ensure that the data (integretity, consistency etc.) is still guaranteed and not broken by the failure of statement s1?
Seperate try/catch block for each statement.Quote:
Originally posted by dullboy
Let me give an example,
try
{
statement s1;
statement s2;
statement s3;
...
}
catch(someException e)
{
...
}
If statement s1 throws an exception, how do you ensure s3 be excuted? Thanks.
In some cases, for example, s1 opens a file, s2 tries to read the file and s3 close the file. if s2 throws an exception, then s3 won't be excuted. In this case, file handle is never close. So based on you guys' answers, I guess I should code like this,Quote:
Originally posted by Andreas Masur
Well...by putting it into the 'catch' block... :D
No...serious, the first question would simply be why you want to execute statement s3 although statement s1 has failed? How can you ensure that the data (integretity, consistency etc.) is still guaranteed and not broken by the failure of statement s1?
try
{
statement s1;
statement s2;
}
catch(const someException& e) // thanks for souldog's comments
{
statement s3;
}
is that correct? Thanks.
try
{
statement s1;
statement s2;
statement s3;
}
catch(const someException& e) // thanks for souldog's comments
{
statement s3;
}
The catch block is only executed if an exception is thrown, so
you need to close the file in both places.
const is not always needed on the exception.
Thanks for your advices. I am also curious in which case const is needed and in which case const is NOT needed?Quote:
Originally posted by souldog
try
{
statement s1;
statement s2;
statement s3;
}
catch(const someException& e) // thanks for souldog's comments
{
statement s3;
}
The catch block is only executed if an exception is thrown, so
you need to close the file in both places.
const is not always needed on the exception.
Well...you should rather use a common idiom named RAII (Resource Acquisition Is Initialization):Quote:
Originally posted by dullboy
So based on you guys' answers, I guess I should code like this,
try
{
statement s1;
statement s2;
}
catch(const someException& e) // thanks for souldog's comments
{
statement s3;
}
is that correct? Thanks.
This will ensure that the file will be always closed... :cool:Code:#include <string>
class CFoo
{
public:
CFoo(const std::string strFilename) { // Open file }
~CFoo() { // Close file }
void Read() { // Read file }
};
int main()
{
try
{
CFoo File("c:\test.txt");
File.Read();
}
catch(...)
{
}
return 0;
}
Well...that would create redundant code...look at my previous reply for a better (in my opinion) solution...Quote:
Originally posted by souldog
try
{
statement s1;
statement s2;
statement s3;
}
catch(const someException& e) // thanks for souldog's comments
{
statement s3;
}
The catch block is only executed if an exception is thrown, so
you need to close the file in both places.
Nice. I like it.Quote:
Originally posted by Andreas Masur
Well...you should rather use a common idiom named RAII (Resource Acquisition Is Initialization):
This will ensure that the file will be always closed... :cool:Code:#include <string>
class CFoo
{
public:
CFoo(const std::string strFilename) { // Open file }
~CFoo() { // Close file }
void Read() { // Read file }
};
int main()
{
try
{
CFoo File("c:\test.txt");
File.Read();
}
catch(...)
{
}
return 0;
}
A little aside :
why should the exceptions be const ?
I'm just interested. I can almost see why, but I'd be interested in the reply.
I always try to learn from these groups and suggestions like these are highly useful.
Many thanks SoulDog.
Darwen.
Oh and to Andreas :
The problem with catch (...) means that when a failure in your program occurs then you won't know why it happened.
A GPF might have occurred (not a file error) and catch (...) will trap this and not pass it on.
I always try to catch only the exceptions which I would normally expect from an operation. If something else happens, then I want to know about it.
Only then can I fix a bug which would normally be hidden by catch(...).
I may be wrong of course....
Darwen.
If you are not going to do anything to the
exception that requires a none constant function call
then catching with const
1. Lets the compiler enforce this.
2. Allows for compiler optimizations.
It is entirely unneccessary.
Thanks SoulDog.
Darwen.
Isn't this a good example for the frequent call to "RTFM" ? From MSDN ("try"):
====
// Example of the try and catch statements
try
{
// Write the file header
file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));
//
// Write the DIB header and the bits
file.WriteHuge(lpBI, dwDIBSize);
}
catch (CFileException* e)
{
::GlobalUnlock((HGLOBAL) hDib);
throw;
}
::GlobalUnlock((HGLOBAL) hDib);
return TRUE;
====
.. where the ::GlobalUnlock is only needed in the catch block because "throw" is called.
I agree with try..catch blocks you'll never know in a multi-line entry what went wrong unless you do :
See what I mean ? Same as had been said.Code:try
{
// line 1
}
catch (whatever)
{
}
try
{
// line 2
}
catch (whatver)
{
}
try
{
// line 3
}
catch (whatever)
{
}
I far prefer functions with boolean values to show success or failure.
Darwen.
Never mind the fact that if we're using MFC compilers we should be using
Darwen.Code:TRY
{
// code
}
CATCH (CFileException, pFileException) // example
{
}
END_CATCH
Why there is rarely a reason to modify the exception itself... :cool:Quote:
Originally posted by darwen
why should the exceptions be const ?
Yes...I simply used it for demonstration purposes and since it was in the original code. The usage of 'catch(...)' should be of course limited (if not avoided).Quote:
Originally posted by darwen
The problem with catch (...) means that when a failure in your program occurs then you won't know why it happened.
A GPF might have occurred (not a file error) and catch (...) will trap this and not pass it on.
I always try to catch only the exceptions which I would normally expect from an operation. If something else happens, then I want to know about it.
Only then can I fix a bug which would normally be hidden by catch(...).
I may be wrong of course....
Nevertheless, eventhough the 'catch(...)' is in there, it does not necessarely protect your application from crashing. Access-violations etc. cannot be caught with that...at least not reliable. I know that some people say, it is working, however, I made the experience that it is not working. In this case, you would rather need to use structured exception handling.
Which actually is a bad example in my eyes since it also creates code redundancy as mentioned earlier... :cool:Quote:
Originally posted by Marco F
// Example of the try and catch statements
try
{
// Write the file header
file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));
//
// Write the DIB header and the bits
file.WriteHuge(lpBI, dwDIBSize);
}
catch (CFileException* e)
{
::GlobalUnlock((HGLOBAL) hDib);
throw;
}
::GlobalUnlock((HGLOBAL) hDib);
return TRUE;
====
.. where the ::GlobalUnlock is only needed in the catch block because "throw" is called.
Well...sorry but I cannot agree here. Based on the shown way I would agree, however, in my opinion one should not go with such a way if there isn't a real good reason for that. You can reduce the scope of the 'try' block to a certain piece of code. In other words, in the given example, reading from a file. If an exception is thrown, you know that something failed while working with the file. Whether it failed to open it or to read from it, it not important in the first place most of the time. Nevertheless, if specific information is required, either there are different exceptions are being throw or you really need to go with the way shown above.Quote:
Originally posted by darwen
I agree with try..catch blocks you'll never know in a multi-line entry what went wrong unless you do :
See what I mean ? Same as had been said.Code:try
{
// line 1
}
catch (whatever)
{
}
try
{
// line 2
}
catch (whatver)
{
}
try
{
// line 3
}
catch (whatever)
{
}
I far prefer functions with boolean values to show success or failure.
What kind of a compiler is a MFC compiler ? Normally I'm only using a C++ compiler ...Quote:
Originally posted by darwen
Never mind the fact that if we're using MFC compilers we should be using
This would be a problem if s3 throws an exception.Quote:
Originally posted by souldog
try
{
statement s1;
statement s2;
statement s3;
}
catch(const someException& e) // thanks for souldog's comments
{
statement s3;
}
The catch block is only executed if an exception is thrown, so
you need to close the file in both places.
const is not always needed on the exception.