Finally in CPP

Started by
20 comments, last by jpetrie 17 years, 6 months ago
If delete throws it doesnt necessarly means the memory is leaked.
Somethng could have happen in the dtr of that memory, such as a file error or something like that.
After setting the pointer to NULL, why not propegate the exception?
The thing is, the most important thing I want when an exception error happen in my program, is to catch where it happend. So I can solve this bug.
It's all about the wheel.Never blindly trust technoligy.I love my internal organs.Real men don't shower.Quote:Original post by Toolmaker Quote:Original post by The C modest godHow is my improoved signature?It sucks, just like you.
Advertisement
then in the catch block use a macro to log it to a file along with __FILE__ and __LINE__

i.e.

try{    delete pointer;}catch (...){    LOG(........);}
Quote:Original post by Enigma
Quote:Original post by Deyja
However, delete CAN throw. In the case where delete throws, the destructor has already been called. Now, delete should only throw when you have corrupted the heap somehow, or aren't deleting a deletable object. All these cases are usually caught by the operating system as an access violation or seg fault, and represent a much more sinister bug.


Just to clarify, delete cannot throw a C++ exception. It may throw an exception of the underlying hardware/operating system (a Windows Structured Exception under Windows), but there is no guarantee that this exception can be caught by the C++ exception mechanism (under Windows only C++ exception mechanisms which are built on top of the Windows Structured Exception mechanism can catch Windows Structured Exceptions. I believe only Visual C++ is implemented this way due to legal reasons).

Σnigma

It can, if the dtr explictly throws a C++ excpetion.

It's all about the wheel.Never blindly trust technoligy.I love my internal organs.Real men don't shower.Quote:Original post by Toolmaker Quote:Original post by The C modest godHow is my improoved signature?It sucks, just like you.
Quote:Original post by Julian90
then in the catch block use a macro to log it to a file along with __FILE__ and __LINE__

i.e.

try{    delete pointer;}catch (...){    LOG(........);}

That is not the problem.
The problem is that after an exception has occured, trying to continue running your program is a suicide.


It's all about the wheel.Never blindly trust technoligy.I love my internal organs.Real men don't shower.Quote:Original post by Toolmaker Quote:Original post by The C modest godHow is my improoved signature?It sucks, just like you.
Quote:Original post by The C modest god
If delete throws it doesnt necessarly means the memory is leaked.
Somethng could have happen in the dtr of that memory, such as a file error or something like that.


Exceptions trigger stack unwinding. Stack unwinding automatically causes destructors to be run (which was the answer to your original question). Raising an exception while one is already pending will systematically terminate the program. Therefore your destructors must not throw, nor rely on operations that may throw. You need the "nothrow guarantee"*.

Quote:The thing is, the most important thing I want when an exception error happen in my program, is to catch where it happend. So I can solve this bug.


When an exception is raised, you should catch it at the point where you can do something about it. That may very well not be "where it happened", which is precisely why exceptions propagate on their own.

Quote:The problem is that after an exception has occured, trying to continue running your program is a suicide.


Just because you were handed a std::bad_alloc or std::out_of_range doesn't mean that your program is doomed. It just means you have to take corrective action.


* There are three level of exception safety guarantees you can provide for an operation. You always need to at least provide the basic guarantee: if an exception is raised during the operation, the program is left in a consistent, if unpredictable state. The class invariants are preserved, etc. With the strong guarantee, an operation must either succeed or have no effect. If an exception is thrown mid-way, the program state must be left unchanged. Finally providing the nothrow guarantee means that the operation just cannot fail.
Both destructors and swap operations (std::swap, std::vector::swap ...) both must provide the nothrow guarantee.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Quote:If delete throws it doesnt necessarly means the memory is leaked.
Somethng could have happen in the dtr of that memory, such as a file error or something like that.

No, the destructor is called before the system reclaims memory. If it throws, the memory leaks.

Quote:
Just to clarify, delete cannot throw a C++ exception. It may throw an exception of the underlying hardware/operating system (a Windows Structured Exception under Windows), but there is no guarantee that this exception can be caught by the C++ exception mechanism (under Windows only C++ exception mechanisms which are built on top of the Windows Structured Exception mechanism can catch Windows Structured Exceptions. I believe only Visual C++ is implemented this way due to legal reasons).

That's what I get for using VC++ then, I guess. But there's no reason the library implementation couldn't throw C++ exceptions. Even if the hardware communicates failure using smoke signals and navy flags, the implementation of delete could translate them into exceptions.
Still pointless. Whatever kind of exception you get from delete, you can't do anything usefull besides ignore it.
in delphi's rtl's code, there's a FreeAndNil procedure, translate it to c++:

template<typename T>inline void FreeAndNil(T*& v){	T* ptr=v;	v=NULL;	delete ptr;}


haha, everything's done :)

or use destructor to simulate finally to take the same effect:
template<typename T>struct doomer{	T*& ptr;	doomer(T*& p):ptr(p)	{	};	~doomer()	{		ptr=NULL;	}};
Veni Vidi Vici
Lets say I recognize in one of the dtr that something is wrong. So I save the position of this wrong thing.
Now I want to stop my program and report it to the user.
I cant do it inside the dtr.
Is there a way to have a function operate immediatly after all the dtr have finished?
It's all about the wheel.Never blindly trust technoligy.I love my internal organs.Real men don't shower.Quote:Original post by Toolmaker Quote:Original post by The C modest godHow is my improoved signature?It sucks, just like you.
Quote:Lets say I recognize in one of the dtr that something is wrong. So I save the position of this wrong thing.
I think you may have the wrong idea about exceptions. Exceptions are not what functions do when they "recognize that something is wrong". Exceptions are thrown to indicate that an operation was not performed, and (sometimes) to explain why.
Quote:Now I want to stop my program and report it to the user.
I cant do it inside the dtr.

Why not?
Quote:
Lets say I recognize in one of the dtr that something is wrong. So I save the position of this wrong thing.
Now I want to stop my program and report it to the user.
I cant do it inside the dtr.
Is there a way to have a function operate immediatly after all the dtr have finished?


If a failure occurs in a destructor, there is very rarely any sane corrective action you can take -- what are you going to try and do if you can't close a file? Try again? And again and again and again? Log the failure and move on. You can do this in the destructor since it doesn't mean throwing.

You do not need to terminate the program in the face of an exception. Exceptions don't mean, "Oh crap, time to quit," they mean that something has failed and the operation cannot be completed.

The catch() handler is the "function" that operates after "all the dtr" of the objects whose lifetime began within the try block have been executed as a result of an exception.

This topic is closed to new replies.

Advertisement