Re: are raw pointers really bad?
Quote:
Originally Posted by
Feoggou
I've read that the STL list throws an exception on push_back if an error occurs. Perhaps it sounds silly, but do I really have to make sure I catch every exception?
Nope----you only need to catch those exceptions which you have some idea how to recover from. If the exception is insurmountable (such as out of memory), you may as well let it propagate and kill the program.
Quote:
the same question applies to using statements as char str[20]; or int x; - if it cannot allocate the memory the program would crash
Since those statements use stack memory, they'll never crash the program unless you're running out of stack space which indicates a problem elsewhere in the code; this should not be a normal concern. Stack overflows usually indicate either that you're trying to put enormous arrays on the stack (put the really big ones on the heap), or you have infinite recursion somewhere (fix it).
Quote:
and I suppose that after the program is ended there might be memory leaks.
On modern systems, it's impossible to have memory leaks after the program is ended. When the process terminates, all of the memory it used, leaked or not, goes back to the OS. The concern is how to avoid memory leaks during execution. To that end, RAII is your friend. So long as all resource deallocation is handled by the destructor of some object on the stack (say a smart pointer, STL container, or custom object), memory leaks are almost impossible even in the face of exceptions.
Re: are raw pointers really bad?
Quote:
Perhaps it sounds silly, but do I really have to make sure I catch every exception?
In many cases, you don't need to care what exceptions might be thrown, you only need to clean up if an exception whose identity is of no interest has been thrown, then you can pass the exception onward.
Code:
void MyDataFunction(void) throw (...) // Explicitly state this function can throw anything
{ // For backward compatibility, it's otherwise implicitly so in C++
int const nData = 500;
CMyDataObject * const aMyData = new CMyDataObject [nData];
try
{
int const * const pResults = RiskyDataCollectorWhichCanThrowFiveExceptions(aMyData, nData);
RiskyDataDisplayWithMoreExceptions(pResults, aMyData, nData);
}
catch (...) // catch anything without learning its identity
{
delete [] aMyData; // Don't let exceptions cause a resource leak!
throw; // Propagate the exception. Some caller might be able to
// recover and display an error message to the user, then
// resume normal program operation.
}
delete [] aMyData; // Normal path, all done.
}
The RAII pattern makes the delete [] and the try/catch unnecessary.
An article called "The Trouble with Checked Exceptions", which is an interview with the lead C# designer, gives a good language-neutral perspective on exception handling and the state of current thought (in some circles at least) on the matter.
The article can be found at <http://www.artima.com/intv/handcuffs.html>.
Re: are raw pointers really bad?
ok, so if I do something like this:
Code:
int* p = new p[200];
(that is, without a try-catch block) and there isn't sufficient free memory for all. That would cause the program to crash. Would there be memory leaks after the program is ended?
and, on the other hand, if I used:
but there isn't sufficient memory left, the program would crash and you mean that there would be no memory leaks because of RAII, right?
Re: are raw pointers really bad?
Quote:
Originally Posted by Feoggou
(that is, without a try-catch block) and there isn't sufficient free memory for all. That would cause the program to crash. Would there be memory leaks after the program is ended?
The program might not crash. std::bad_alloc might be thrown instead, in which case it is possible to recover, to some extent. There would not be a memory leak in a modern OS since the OS would reclaim the memory used after the process terminates; otherwise it depends on whether the other dynamically allocated objects use RAII (or maybe not, if the crash means that there is no stack unwinding).
Re: are raw pointers really bad?
Quote:
Originally Posted by
Feoggou
and, on the other hand, if I used:
but there isn't sufficient memory left, the program would crash and you mean that there would be no memory leaks because of RAII, right?
Considering your proposition that there is no enclosing try/catch in your first example, the essential outcome would be pretty much the same in both cases.
Doing a bit of nitpicking, I would say the second one is even worse because running out of stack space is such a fatal condition that there's hardly a chance to recover from it, and AFAIK there's no exception thrown in that case. (Well, in .NET there actually is one, but that's not what we're talking about here.) Also, laserlight pointed out (although in parentheses) that there may be no stack unwinding in the case of running out of stack space. And I estimate the chance for that actually very high so that I think it's unlikely that RAII will really help here. (Of course that does not mean I think that allocating objects on the stack is generally a bad idea. This is only an issue if you are allocating really large objects, mostly arrays, on the stack, maybe even recursively, and that's definitely not recommended anyway.)
And, as already pointed out by laserlight as well, there will be no system-wide memory leaks after an app crash because the OS takes care of that. (And that's why the outcome is pretty much the same in both cases.)
Re: are raw pointers really bad?
ok, thanks guys for your help. It's clear to me now.
Re: are raw pointers really bad?
In theory, when a new fails, the *new_handler is called to try to free up memory. The new_handler frees up memory and returns execution to new to try again. The cycle continues add infinitum, until either the new succeeds, or the new_handler tires and returns an std::bad_alloc compatible exception.
You shouldn't care, but from an external view, this means two things:
1- new ALWAYS* returns std::bad_alloc when it fails (not might)
2- In theory, by the time you receive the bad_alloc, the system has already tried to recover from it. It is just politely telling you it is about to fail.
Of course, this is a quality of implementation thing, and results might differ on different platforms.
*If no new handler is present, it just immediately throws bad_alloc.
*Except nothrow new of course, but even nothrow new calls the new_handler.