16

What is the behavior of calling a null function pointer?

void (*pFunc)(void) = NULL;  
pFunc();

Why is it advisable to initialize yet unused function pointers to NULL?

Mat
  • 202,337
  • 40
  • 393
  • 406
Vorac
  • 8,726
  • 11
  • 58
  • 101

3 Answers3

15

In C and C++, this is called undefined behaviour, meaning that this can lead to a Segmentation fault, nothing or whatever such a case will cause based on your compiler, the operating system you're running this code on, the environment (etc...) means.

Initializing a pointer to a function, or a pointer in general to NULL helps some developers to make sure their pointer is uninitialized and not equal to a random value, thereby preventing them of dereferencing it by accident.

Halim Qarroum
  • 13,985
  • 4
  • 46
  • 71
  • 1
    This will lead to a segmentation fault in 99% of the cases and on many systems/architectures. The standard does not, however, explicitly state that it will happen. – Halim Qarroum Feb 26 '13 at 13:35
  • I think it is "unspecified" behavior, but not really undefined. What if memory 0x0 is addressable and "executable"... –  Feb 26 '13 at 15:18
  • @VladLazarenko: C and C++ say that this is "undefined behavior", that is, anything can happen. Now, it that address happens to be "executable", then it may very well result in it being executed... but it may also result in it not being executed. I recall that a while ago there was a Linux kernel bug based exactly on that distinction... – rodrigo Feb 26 '13 at 15:23
  • 1
    @rodrigo: Right. What I am wondering is wether a standard explicitly states that it is not allowed to have 0x0 as a valid memory address. Then it would be "undefined behavior". If it doesn't say that then it'd be unspecified — those are essentially two different things. –  Feb 26 '13 at 15:30
  • 2
    @VladLazarenko: The standard says nothing about address 0x0. About `NULL` pointers it says just two things: that no valid object of function has address `NULL`; and that referencing / calling a `NULL` pointer is UB. Now, an implementation may choose to document that particular behavior and may even specify the binary value of a `NULL` pointer. For a nicer explanation see [this other question](http://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior). – rodrigo Feb 26 '13 at 16:53
  • @rodrigo, the standard guarantees that if you use 0 for a pointer, it is taken to be NULL (in the sense you describe). I.e., instead of `p == NULL` you can say `p == 0` or just use `p` in a boolean context `if(p) { ... }`. – vonbrand Feb 26 '13 at 19:08
  • 5
    @vonbrand: You're right: the literal `0` can be used as the `NULL` pointer constant. But that doesn't mean that the NULL pointer is at address 0x0 or that it is an all-zero bit pattern. The actual address of the `NULL` pointer is _implementation defined_. Confusing, I know, but that's it. – rodrigo Feb 26 '13 at 21:22
2
  1. What happnes when u try to access NULL? Following is true about data as well as code, and this is what happens when you try to read NULL(or any address from 0 to 4096,i.e atleast first page of segment). Root cause of this lies in OS and microprocessor segmentation/paging architecture

    When you try to access NULL( or 0) address, in any of data or code section, it causes segmentation fault(which is actually a killer page fault). First page of section is treated as out of( or invalid part of) virtual address space. That is purposefully that first page is kept invalid( or not present) so atleast one address that pointer contains could be represented as invalid in program at execution time.

    Page descriptor of the 1st page(which contains virtual address 0, NULL), has first bit "present" as 0 (means its invalid page). Now if you try to access NULL pointer(0 address) it will cause to raise a page fault as page is not present, and OS will try to handle this page fault. When page fault handler see that its trying to access 1st page, which is treated as a invalid part of virtual address space it kills the process. This is all about user space process. If you try to access NULL pointer in system process(kernel level code), it will fail your OS an crash the system.

    Links: http://en.wikipedia.org/wiki/Page_fault#Invalid http://en.wikipedia.org/wiki/Memory_protection#Paged_virtual_memory http://pdos.csail.mit.edu/6.828/2005/readings/i386/s05_02.htm

    Above is sufficient bt as i think u should read this as well http://www.iecc.com/linker/linker04.txt

  2. Why function pointer is initialized to NULL? Although if you try to call the with NULL its going to give page/segment fault. NULL signifies its invalid function. If it contains any garbage address but in valid virtual address space of code section, i think any code at that address will be called, which could be even more disaster(spl in case of real time systems). Initialize funcp = funct_foo_name + 1; now call function using function pointer. Function pointer points to valid virtual address space of code section. bt function will start from incorrect place to execute. which could result into wrong code execution or wrong order.

rahul.deshmukhpatil
  • 977
  • 1
  • 16
  • 31
  • 1
    You make way too many assumptions that don't necessarily hold. I've worked on platforms where address 0 isn't treated any different from address 42890. – Nik Bougalis Feb 26 '13 at 18:35
  • 1
    As the [Ten Commandments](http://www.lysator.liu.se/c/ten-commandments.html) teach us, "Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end." – vonbrand Feb 26 '13 at 19:11
  • @NikBougalis: You are true. What I mean by first page or invalid address range of 0 to 4096(which is standard page size of x386) is the intial invalid virtual address space. As i think its a OS dependent stuff, how much of initial part of virtual address space range it thinks as invalid – rahul.deshmukhpatil Feb 27 '13 at 06:12
0

It's advisable for the same reason as initializating "normal" (data) pointers to NULL: because it potentially makes some errors easier to track down. Opinions on whether this is useful or not of course vary :-)

Philip Kendall
  • 4,304
  • 1
  • 23
  • 42