48
  try {
        int* p = 0;
        *p = 1;
    } catch (...) {
        cout << "null pointer." << endl;
    }

I tried to catch the exception like this but it doesn't work,any help?

0xC0DEFACE
  • 8,825
  • 7
  • 34
  • 35
mindhacks
  • 509
  • 1
  • 4
  • 6
  • 31
    For VC++ specifically, `catch(...)` will catch AV if you compile with `cl.exe /EHa`. However, if you ever do this, an angry C++ god will immediately strike you down with lightning on the spot, so forget I told you that. – Pavel Minaev Dec 01 '09 at 03:08
  • 11
    Avoid crashing my program, or get struck down by lightning. An age-old programmer's dilemma. – Nate C-K Dec 01 '09 at 05:57
  • 3
    Don't confuse C++ exceptions with Microsoft's poorly-named system "exceptions". – Lightness Races in Orbit Aug 11 '11 at 00:56

12 Answers12

72

There's no such thing as "null pointer exception" in C++. The only exceptions you can catch, is the exceptions explicitly thrown by throw expressions (plus, as Pavel noted, some standard C++ exceptions thrown intrinsically by standard operator new, dynamic_cast etc). There are no other exceptions in C++. Dereferencing null pointers, division by zero etc. does not generate exceptions in C++, it produces undefined behavior. If you want exceptions thrown in cases like that it is your own responsibility to manually detect these conditions and do throw explicitly. That's how it works in C++.

Whatever else you seem to be looking for has noting to do with C++ language, but rather a feature of particular implementation. In Visual C++, for example, system/hardware exceptions can be "converted" into C++ exceptions, but there's a price attached to this non-standard functionality, which is not normally worth paying.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • 1
    "The only exceptions you can catch, is the exceptions explicitly thrown by throw expressions" - and default `operator new` (it may be implemented using explicit `throw`, sure, but there's nothing that requires it to do that; it may well be an intrinsic). – Pavel Minaev Dec 01 '09 at 03:12
  • 1
    There are more places in C++ that can throw besides `operator new`, `dynamic_cast` to reference type being another example, but that wasn't the point. The point is that you can only catch C++ exceptions. Of course, claiming that they can only be thrown by a user-level `throw` is incorrect. – AnT stands with Russia Dec 01 '09 at 03:16
  • Dereferencing a null pointer/division by zero does not produce undefined behavior. It throws an exception, the difference being that it's an OS exception, not a C++ one. – Michael Chourdakis Feb 14 '13 at 14:53
  • @Michael: There's no such thing as "OS exception" in the realm of C++ language. Division by zero, as well as null pointer dereference produces *undefined behavior*, not an exception of any kind. – AnT stands with Russia Feb 15 '13 at 07:25
  • On Linux, at least, a null dereference generates a SIGSEGV that can be handled by user code (by installing a user handler for that signal), but it's not likely to take you anywhere useful, and the stack would not be unwound as you expect for normal C++ exceptions. – Brian A. Henning May 16 '16 at 23:37
  • 1
    @Lotharyx: Even that only applies in the dereference actually occurs. A C++ compiler is allowed to "foresee" any occurrences of undefined behavior and generate completely unrelated, arbitrary code in situations that would otherwise lead to, say, null pointer dereference. And this is not an abstract point. Compilers like GCC are well-known to optimize their code under the assumption that "this will never happen since the behavior would be undefined". – AnT stands with Russia Dec 10 '16 at 15:40
  • 1
    E.g. if you have `*p = 42` in your code, the compiler is legally free to assume that pointer `p` is *never* null and generate the code under that assumption. This can easily drive the code into some completely different and unpredictable manifestation of undefined behavior than `SIGSEGV` for a null pointer dereference. – AnT stands with Russia Dec 10 '16 at 15:48
30

You cannot. De-referencing a null-pointer is a system thing.

On Linux, the OS raises signals in your application. Take a look at csignal to see how to handle signals. To "catch" one, you'd hook a function in that will be called in the case of SIGSEGV. Here you could try to print some information before you gracefully terminate the program.

Windows uses structured-exception-handling. You could use the instristics __try/__except, as outlined in the previous link. The way I did it in a certain debug utility I wrote was with the function _set_se_translator (because it closely matches hooks). In Visual Studio, make sure you have SEH enabled. With that function, you can hook in a function to call when the system raises an exception in your application; in your case it would call it with EXCEPTION_ACCESS_VIOLATION. You can then throw an exception and have it propagate back out as if an exception was thrown in the first place.

GManNickG
  • 494,350
  • 52
  • 494
  • 543
  • 1
    You must also use `/EHa` when using `_set_se_translator`. – Pavel Minaev Dec 01 '09 at 03:25
  • I find `_set_se_translator` is only of limited use because (from msdn) ... "In a multithreaded environment, translator functions are maintained separately for each thread. Each new thread needs to install its own translator function. Thus, each thread is in charge of its own translation handling. _set_se_translator is specific to one thread; another DLL can install a different translation function." ... So if you don't control the creation of all threads that call your code you cannot use it. Having said that boost.test uses this to great effect, but this is single threaded – iain Dec 01 '09 at 08:46
  • @iain: How does boost.test use it? That's surprising since boost works on so many non-MS platforms. – Joseph Garvin Dec 30 '10 at 07:36
  • 2
    @Joseph: While boost is generally platform agnostic it does tend to make use of platform specific code internally if it makes sense to do so. In this case it creates an empty implementation of _set_se_translator for non windows platforms (see boost-1.37.0/include/boost/test/impl/execution_monitor.ipp). This works very well for boost.test where it assists debugging on windows platforms where it is available and works as normal on other platforms. – iain Jan 04 '11 at 09:12
  • @Joseph: ... I think that there are also special handlers for signals on unix but we tend to catch most of these type of issues in windows. As we develop in windows and use the unit tests to ensure that we don't break the unix code. – iain Jan 04 '11 at 09:44
13

There is a very easy way to catch any kind of exception (division by zero, access violation, etc.) in Visual Studio using try -> catch (...) blocks.

A minor project tweaking is enough. Just enable the /EHa option in project settings. See Project Properties -> C/C++ -> Code Generation -> Modify the Enable C++ Exceptions to "Yes With SEH Exceptions". That's it!

See details here: http://msdn.microsoft.com/en-us/library/1deeycx5(v=vs.80).aspx

Kimbluey
  • 1,199
  • 2
  • 12
  • 23
Volodymyr Frytskyy
  • 1,233
  • 11
  • 15
9

Dereferencing a null (or pointer that's past-the-end of array, or a random invalid pointer) results in undefined behavior. There's no portable way to "catch" that.

Pavel Minaev
  • 99,783
  • 25
  • 219
  • 289
5

C++ doesn't do pointer checking (although I suppose some implementations could). If you try to write to a null pointer it is most likely going to crash hard. It will not throw an exception. If you want to catch this you need to check the value of the pointer yourself before you try to write to it.

Nate C-K
  • 5,744
  • 2
  • 29
  • 45
  • 5
    It really depends on the implementation and the OS. E.g. on Win32, dereferencing a null pointer will result in an access violation (as any other platform with memory protection, really), but Win32 AV is a structured exception, and it can be caught by a C++ compiler that implements its own exception model on top of Win32 SEH - for example, VC++ with `/EHa` compilation flag. Of course, it is still sheer evil (and unportable). – Pavel Minaev Dec 01 '09 at 03:07
  • 5
    Speaking of memory protection, I started writing C on DOS, when writing to a null pointer usually meant you'd be rebooting your machine. At least DOS booted fairly quickly. – Nate C-K Dec 01 '09 at 03:14
  • @Nate C-K: I once messed up some pointers in a C program on DOS and before hanging the computer printed the content of the ROM. Or at least that's how I interpreted what I saw on the screen back then. – Giorgio May 05 '12 at 21:59
  • As you say "some implementations". I suppose languages that throw nullpointer exceptions (eg java) do always do that check for 0. Although this is a fairy big overhead, a speed comparison would be nice. – TheTrowser Sep 25 '15 at 15:55
  • @TheTrowser: I suspect the overhead is minuscule, and there are lots of places where the check could be optimized away. – Nate C-K Sep 26 '15 at 01:33
3

Generally you can't. Even if you could it would be like trying to put a band aid on a submarine that has sprung a leak.

A crippled application can do far more damage than one that has crashed. My advice here would be to let it crash then fix why it crashed. Rinse. Repeat.

0xC0DEFACE
  • 8,825
  • 7
  • 34
  • 35
2

As others have said, you can't do this in C++.

If I can make a broader point: even in a language that allows you to catch it, the better action is to not touch null pointers. Catching an error when it's already blown up in your face, then deciding to just move on like it didn't happen, is not a good coding strategy. Things like null pointer dereference, stack overflow, etc., should be seen as catastrophic events and defensively avoided, even if your language allows you to react to it differently.

asveikau
  • 39,039
  • 2
  • 53
  • 68
1

There is no platform independent way to do this. Under Windows/MSVC++ you can use __try/__except

But I wouldn't recommend doing it anyway. You almost certainly cannot recover correctly from a segmentation fault.

Axel Gneiting
  • 5,293
  • 25
  • 30
  • He's specifically asking about null pointer dereference, which is certainly quite recoverable (as it doesn't corrupt memory etc). Still not a good idea, but for different reasons. – Pavel Minaev Dec 01 '09 at 03:11
  • Indeed, the only exception I had a bit difficulty from recovering from was a stack-overflow. In fact, I couldn't. I don't think it's possible, as throwing an exception uses too much stack, at least on Windows (Linux provides an alternate stack for exceptions). You do have enough time to spawn a new thread and try to save as much information as you can, though. – GManNickG Dec 01 '09 at 03:21
  • I don't agree that it is recoverable, since it represents a logical error in the program, and the only way to fix logical errors is to alter the program itself. It's trappable, but trappable doesn't mean recoverable. If your program detects a logical error, such as this, it should crash early, crash often. – DrPizza Dec 01 '09 at 07:11
0

If you wanted to you could just do the pointer checking yourself and throw...

if (p == nullptr) throw std::exception("woot! a nullptr!")
p->foo();

so course this would only be to debug the problem, the nullptr should not occur in the first place :)

Jan Wilmans
  • 665
  • 6
  • 10
0

Short answer- you can't in a portable or standard way, because bugs like this are potentially corrupting the process itself.

Long answer- you can do more than you might think, and definitely more than the default of the program just crashing. However, you need to keep 3 things in mind:
1) These bugs are MORE severe than exceptions and often cannot present as exceptions to your logic.
2) Your detection and library handling of them WILL be platform-dependent on the back end, even though you can provide a clean abstract interface for public consumption.
3) There will always be some crashes that are so bad you cannot even detect them before the end.

Basically, faults like segfaults or heap corruption are not exceptions because they're corrupting the actual process running the program. Anything you coded into the program is part of the program, including exception handling, so anything beyond logging a nice error message before the process dies is inadvisable in the few cases it isn't impossible. In POSIX, the OS uses a signaling system to report faults like these, and you can register callback functions to log what the error was before you exit. In Windows, the OS can sometimes convert them into normal-looking exceptions which you can catch and recover from.

Ultimately, however, your best bet is to code defensively against such nightmares. On any given OS there will be some that are so bad that you cannot detect them, even in principle, before your process dies. For example, corrupting your own stack pointer is something that can crash you so badly that even your POSIX signal callbacks never see it.

Zack Yezek
  • 1,408
  • 20
  • 7
0

In VC++ 2013 (and also earlier versions) you can put breakpoints on exceptions:

  1. Press Ctrl + Alt + Delete (this will open the exception dialog).
  2. Expand 'Win32 Exceptions'
  3. Ensure that "0xC0000005 Access Violation" exception is checked.

Now debug again, a breakpoint will be hit exactly when the the null dereference happened.

0

There is no NULL pointer exception exist in c++ but still you want to catch the same then you need to provide your own class implementation for the same.

below is the example for the same.

class Exception {

public:
   Exception(const string& msg,int val) : msg_(msg),e(val) {}
  ~Exception( ) {}

   string getMessage( ) const {return(msg_);}
   int what(){ return e;}
private:
   string msg_;
   int e;
};

Now based on NULL pointer check it can be threw like , throw(Exception("NullPointerException",NULL)); and below is the code for catching the same.

 catch(Exception& e) {
      cout << "Not a valid object: " << e.getMessage( )<< ": ";

        cout<<"value="<<e.what()<< endl;
   }
user2997518
  • 812
  • 6
  • 17