I have a little function (in a DLL) which looks like this:
int my_function(const char* const s)
{
try {
return my_object->do_something_with(s);
} catch (exception& e) {
return ERROR_CODE;
}
}
I thought that the try-catch block would prevent anything which might happen inside my_object
from propagating to the outside. Unfortunately, I was wrong, and my program which calls this function (from VB) just stopped working because I had passed a null pointer argument.
So, why is my try-catch block not working as (I) expected? Is there a workaround? I used to program a lot in Java and I think it would have worked there ...
It would have worked in Java, because in Java a NullPointerException
is thown. In C++, there's no such ubiquitous exception, dereferencing a null pointer will just give a segmentation fault.
Additionally, in C++ there is no enforced exception type hierarchy. An exception of any type may be thrown; exceptions don't have to derive from std::exception
. (So even if someone had defined a class NullPointerException {};
, but had not designated it to derive from std::exception
, you still wouldn't be catching it.)
Dereferencing a null pointer in C++ is undefined behavior. This means the C++ standard doesn't put any limits on what may happen. Anything is permitted - a particular implementation might document its own behavior, or it might not. If it doesn't, the behavior might be consistent and predictable, or it might not.
In general it's best to assume that undefined behavior will cause your computer to catch fire (or format the hard disk). Just don't provoke it. Of course it's difficult to avoid errors in the first cut of your code, so when you do it by accident and your computer doesn't catch fire, then you were lucky, fix the bug and move on. Your function could be rewritten:
int my_function(const char* const s)
{
if (s == 0) return ERROR_CODE;
return my_object->do_something_with(s);
}
Alternatively you could fix the caller to not pass a null pointer in the first place, or you could fix do_something_with
to accept a null pointer. C++ functions with pointer parameters should document whether or not null pointers are permitted.
Different people will write the test (s==0)
differently - it could be (s==NULL)
or (NULL==s)
or (!s)
. Pick one you like.
In practice of course, compilers have good reasons not to set your computer on fire, and modern OSes try to ensure that badly-behaved apps don't massively inconvenience other apps. So on most systems, most of the time, when you dereference a null pointer you'll get some kind of hardware exception or signal, or your process will be killed, or perhaps on an embedded system the device will lock up and need a reboot.
You will not in general get a C++-style software exception that you can catch with any kind of catch clause, although Windows does have a feature called SEH which you can use to get that behavior.
In C++, anything can be thrown, and that anything does not necessarily derive from std::exception
, which I'm assuming you're catching (using namespace std?).
If you want to catch everything that can possibly be thrown, you can use a catch-all, catch (...)
. This will catch any exception, but you won't know what the exception it caught is. It's always better to catch specific exceptions, where possible.
Note that normally, a catch all will not handle lower level exceptions such as access violations. If you're using Windows and Visual Studio, you can configure your project to make catch-all blocks handle these exceptions with /EHa, but doing this is often dangerous and not suggested.
c++ faq items regarding exceptions might help you understand c++ exceptions better.
Lots of people programming in java have a problem understanding pointers and references, so if the program stopped working, maybe it was due to a crash (segmentation fault due to dereferencing NULL?)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With