Why does Software Crash #1 – The Access Violation


Pop quiz: what does this line of code do when executed?

           

            int foo = (*((int*)0));

 

If you’re an astute reader, you can solve the answer just by reading the title of the blog post. But, more interestingly, let’s forget about that buzzword and analyze exactly what’s happening. The access violation is probably the most common crash in unmanaged software, so let’s break it down piece by piece to discover what’s happening.

 

      int foo;

      int * ip = NULL;

      foo = *ip; //crash!

 

On the first line, we declare an integer variable named “foo”.

 

The second line declares a pointer to an integer named “ip”, and initializes this value to NULL (which is simply a fancy term for 0). Pointer variables “point” to a location in memory. In this case, we initialize it to point to the address NULL, or 0, of memory. Location “0” is in area of memory reserved by our operating system.

 

The third line attempts to grab the value of address 0, which is prohibited, and assign it to our variable “foo”. Our operating system smartly catches this and says “No way- you can’t see my reserved memory location!”. Our operating system shuts down this badly behaving application with an error like the following:

 

Unhandled exception at 0x004173c8 in cpractice.exe: 0xC0000005: Access violation reading location 0x00000000.

 

This error message is a bit cryptic, but it’s understandable if broken down. 0xC0000005 is the error code designation for an Access Violation. 0x00000000 is the location that we tried to read (this is our NULL value!). And, 0x004173c8 is the arbitrary memory location where our application happened to be running at the time of the crash.

 

AV’s can happen for both reading and writing, which is part of the reason that they are so common. Pointers in general are one of the most challenging topics in computer science, which is yet another reason this crash is so commonly seen.

 

-Greg


Comments (7)

  1. Anonymous says:

    😉

    It will try to read 4 (or 2, or to be clear sizeof(int)) bytes residing at 0x00000000 address.

    Your assumption that this will fail – is somethat wrong.

    You did not mention that kind of platform you are going to execute this line of code.

    Yep. For Win32 processes – OS protect lowest 4Mb (hmm, is it realy 4Mb or 4Kb only ?) of memory space from reading/writing.

    See http://support.microsoft.com/kb/q125691/ for a reference.

    Thus – while trying to read anything from this area (including from address 0) in user-mode Win32 process you will get page fault that will be translated to exception with code EXCEPTION_ACCESS_VIOLATION.

    But in DOS – this will be completely legal code and you will get some information from interrupt vector table (becouse IVT reside at this addresses)

    BTW, Even in Win32 – this is legal code. You can plug some exception handler for AV exception and perform some magic based on address accessed.

    For example you can see how you can allocate memory dynamicaly as result of exceptions at http://msdn.microsoft.com/library/en-us/memory/base/reserving_and_committing_memory.asp

    If you do not plug own magic – by default Microsoft magic is simply displaying a pretty nice message box with details about address of instruction and data been accessed.

    As well in more recent versions – they added a execution of DrWatson program to send a pretty report back to home.

    I hope that everything will be clear now 😉

  2. Anonymous says:

    Correct about spotting some of my assumptions.

    An NT based operating system won’t just throw an AV for OS reserved memory as well- if you try to access memory reserved by another application, the same error will apply. (Actually, as I think about this, this may only be true if you’re not running as Administrator- I’d have to investigate that further).

    The Watson dialog is certainly a UI improvement over a "0xC0000005" error- I’d like to do a post on exactly what we do with said data when it’s submitted. In the mean time, click "Send" and we’ll keep busy fixing crashes. 🙂

  3. Anonymous says:

    Chris Flaats blog gives a good exlpanation of the Watson and links out to the mini-dump information site on msdn. Just if anyone was confused what "Watson" is:

    http://weblogs.asp.net/cflaat/archive/2003/07/24/51598.aspx

  4. Anonymous says:

    Greg: A tiny correction to your comments. NT-based OS will always throw exceptions if you try to access memory specialy protected from you (just like Win9X one ;-). All thouse exception raised in page fault handler if he unable to dispatch exceptions on his own (he is able to dispatch write-watch exceptions / paged out memory or memory mapped files and a few others).

    You are free to catch them and ignore or hack, terminate process/thread or attach debugger application based on your own logic.

    The only difference is default unhandled exception handler code provided by Microsoft. It will or will not show any pretty dialogs based on configuration options and user settings.

    As well I do not understand your words "memory reserved by another application". Windows (even 95) allocate "own private address space" for each process.

    There are a few ways to read another process memory – using specialy created shared memory region (using CreateFileMapping http://msdn.microsoft.com/library/en-us/fileio/base/createfilemapping.asp ) or by injecting threads to be run inside another process (using CreateRemoteThread http://msdn.microsoft.com/library/en-us/dllproc/base/createremotethread.asp ).

    There is no way to directly access memory of another process.

    Probably you mean something else by "another application" – but I’m unable to understand this.

    ;-))

  5. Anonymous says:

    More on the topic at the above link.