I'm teaching myself techniques of programming with exception safety mode of ;) and I wonder if dereferencing a pointer could ever throw an exception? I think it would be helpful for all C++ programmers to know all operations that are guarantied to not throw so I would be very grateful if someone could compose such list.
dereferencing occurs at runtime, and at a very low level(assembly/machine level), thus it cannot throw anything, it will however raise and exception, such as EXCEPTION_ACCESS_VIOLATION
or SegFault on linux/unix.
(this assumes raw pointers are being used)
If it's a simple pointer (and not some autopointer object or iterator, etc.) then the act of dereferencing can't throw an exception, because dereferencing on its own doesn't do anything. In the compilation process, dereferencing a pointer is just a way of telling the compiler to compose an instruction that does something with what that pointer points to. If the pointer is invalid and you try to write to it with a dereferenced expression, then it certainly will (or should) error out.
As an example:
int *p = 0xFFFFFFFF; // Invalid pointer
*p; // Dereferenced, but since it doesn't do anything there's no error
*p = 0; // Dereferenced write, so it will halt and catch fire
Dereferencing an invalid pointer is undefined behavior, which the implementation can then define as a thrown exception. This is very uncommon in C++, although it's the rule in some other languages.
You can catch memory access exceptions using std::signal( my_handler, SIGSEGV );
, although that still depends on platform support, and the Standard does not allow you to translate it into a C++ exception.
I understand that Microsoft has their own "managed" exceptions or some such, which perhaps could be caught with that mechanism and rethrown in C++ conventions. Or maybe that's forbidden; I don't know.
Dereferencing a simple pointer (T*
) can lead to Undefined Behavior if there is no valid object where the pointer points to. It's the nature of UB that the result might be anything, including, but not limited to, a C++ exception. One could indeed imagine an implementation that would check pointers on access and throw an exception. However, I doubt that such an implementation of C++ will ever exist (if you can spare the runtime overhead of doing this, why use C++?) and the common behavior on most platforms is to either muddle on (if the memory in question is allocated to the process) or crash. On some platforms there are ways to intercept such crashes (like Windows' Structured Exceptions).
However, the unary operator*()
might be overloaded, and usually is for smart pointers and iterators. Such implementations can certainly do anything their implementors want, including, but not limited to, throwing an exception. But again due to runtime overhead, common smart pointer implementations only check in debug builds (usually using some form of an assertion), but not in release builds. (A notable exception are the iterators in recent Visual C++ implementations, which do get quite some heat for this unusual behavior.)
There is a very strong tradition in C++ to differentiate between errors the programmer could have prevented (like accessing an array out of bounds) and errors that programmers could not have prevented (like a network connection dying). For raw speed, the former usually lead to UB, because checking them every time would cost performance. It's left to programmers to check where appropriate and necessary.
You can see this distinction in the definition of the standard library's exception hierarchy, which splits into preventable std::logic_error
and unpreventable std::runtime_error
.