1

I just wanted to know if we can skip the segmentation fault at runtime and write something at memory location of NULL . As of now i believe its a very sacrosanct place and you cant do anything there. I tried a little piece of code.

   #include<iostream>
   #include<stdio.h>
   #include<conio.h>
   #include<stdlib.h>
   using namespace std;            
   int main()
   {
     int *p = NULL;
     int z=6;
     p= &z;
     std::cout << "value of p is :" << *p;   
     p=NULL;
     *p=5;  // Will give segmentation fault as dereferencing of NULL is not allowed
     std::cout << "value of p is :" << *p;   
     getch();
     return 0;      
  }

I know dereferencing the NULL memory allocation is not possible and hence it cant be assigned any value . Doing so gives us segmentation fault. Just for an inquisitive nature, if we can cheat and write at NULL?

Invictus
  • 4,028
  • 10
  • 50
  • 80
  • Why do you want to *cheat* the compiler? Want to *feel* geeky? – Nawaz Jan 29 '12 at 08:23
  • What do you think is causing the segfault? (Hint: it's the write to address 0.) – Mat Jan 29 '12 at 08:24
  • It's not the compiler you need to cheat--it's the OS. Good luck with that... – Drew Hall Jan 29 '12 at 08:25
  • @Nawaz actually i corrected my heading . Its not about cheating the compiler as compiler wont throw the error in first place , but it will result into Run- time error . Just wanted to know if NULL is actually a sacrosanct place. Thanks newaz – Invictus Jan 29 '12 at 08:25
  • @dku.rajkumar Will definitely work on it from today onwards . Thanks newaz – Invictus Jan 29 '12 at 08:26
  • Here's an example of someone who is having problems finding/fixing bugs because his system doesn't crash on accesses through a NULL pointer: http://stackoverflow.com/questions/8990311/handling-null-pointers-on-aix-with-gcc-c – Michael Burr Jan 29 '12 at 09:44

7 Answers7

6

In a typical modern system, there is actually no memory mapped at virtual address 0. It's simply not there at all. The CPU itself is what raises the segmentation fault when you try to write to address 0.

There is a physical address 0, but modern operating systems have virtual memory mapping that gives each process its own custom address space. That address space includes no mapping for virtual address 0.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
  • So, that's not as if virtual address of 0 was treated in any special way by CPU, just no mapping to actual physical memory were done by the OS - correct? – Alexey Kukanov Jan 29 '12 at 08:33
  • That's correct. The same segmentation fault would happen when accessing any virtual address that had no backing store. – Greg Hewgill Jan 29 '12 at 08:35
  • 1
    No rule or standard requires a NULL pointer to point to address zero though. (Though it would be very annoying if zeroing memory didn't NULL pointers.) – David Schwartz Jan 29 '12 at 08:38
  • @GregHewgill Thanks a lot for your enlightenment :) – Invictus Jan 29 '12 at 08:38
  • @DavidSchwartz: yes, that's why I said "typical modern system". The last system I used where a "null" pointer wasn't 0, was Logitech Modula-2 for 16-bit DOS (it was FFFF:FFFF). – Greg Hewgill Jan 29 '12 at 08:40
  • @GregHewgill Nothing in your answer suggested that it was possible for NULL to point anywhere other than at address zero. Your reference to a "typical, modern system" was about what was mapped at address zero, not about where NULL points. – David Schwartz Jan 29 '12 at 08:44
3

It's not the compiler preventing you from doing that, it's your operating system.

Consider following C code

int main(int argc, char *argv[])
{
    int* p = 0;
    *p = 42;
    return 0;
}

Compiler translates it to something like this in ASM

    .file   "test.c"
    .def    ___main;    .scl    2;  .type   32; .endef
    .text
    .globl  _main
    .def    _main;  .scl    2;  .type   32; .endef
_main:
LFB0:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    andl    $-16, %esp
    subl    $16, %esp
    call    ___main
    movl    $0, 12(%esp)
    movl    12(%esp), %eax
    movl    $42, (%eax)
    movl    $0, %eax
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
LFE0:

notice

 movl    $42, (%eax)

This instruction tries to write 42 to location pointed by %eax, which was set to 0 above.

And as far as I know if you are working with virtual memory, location 0 for your application is not location 0 in the real memory. I've read somewhere that bootloader writes something to the start of memory or something like that, but I may be wrong here.

SpyBot
  • 487
  • 2
  • 6
  • 16
2

Well, you can try doing it, and depending on the compiler, OS, etc., you might even get away with it, and store something there (wherever "there" really is).

Then again, your program might get shut down with an access violation, or int might format your hard drive, or if it's connected to the right hardware to do so, your computer might launch a few nuclear missiles...

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
2

If the operating system allowed you to map something at address zero, you could then dereference a NULL pointer without a problem. Alternatively, you could modify the compiler and/or headers so that NULL had some value other than all zero bits (casting an integer zero to a pointer doesn't have to yield a value that is all zeroes bitwise). Then you could map something at the address that NULL maps to and it would work.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
1

No You cannot and No you should not even try! You will end up with an Undefined Behavior if you do so.

When a pointer is made NULL, it simply means that it is pointing to something that is invalid, something not meaningful.

So you cannot tell the compiler that point to something that is not valid and then then try to save something meaningful there, It simply doesn't make any sense.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
1

There is no portable way to do that (good thing too if you ask me)

Some platforms may allow it (usually those without an MMU), but you'll be happier in the long run if you don't even try to disable it. NULL pointer references cause errors for a reason, usually better to know that your pointer is set to NULL (or possibly uninitialized) than ignoring it and moving on.

Imagine for example the case where malloc() fails to allocate memory and you try to use it without checking. You'd likely want to know.

Joachim Isaksson
  • 176,943
  • 25
  • 281
  • 294
1

I may be wrong here, but I think the compiler is letting you dereference NULL — after all, SIGSEGV is a signal that kills the program during runtime. The compiler is compiling the code, but the operating system memory management does not let your program play with the memory contents at 0x0.

Maybe this is handled by some of the libraries linked in by the compiler, which may refuse to let you access 0x0 even if the current computer actually allows so.

I guess you may walk into a system that allows 0x0 to be used, but it has been used for so long to represent "invalid positions" that the system libraries or OS will probably refuse that to avoid breaking code with NULL checks.

njsg
  • 125
  • 8
  • I guess you are correct . That is Why i modified the heading Quickly and termed it as run-time instead of compiler. Thanks a lot newaz – Invictus Jan 29 '12 at 08:35