Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is dereferencing null pointer valid in sizeof operation [duplicate]

I've come across a snippet of code that to me should crash with a segmentation fault, and yet it works without a hitch. The code in question plus relevant data structure is as follows (with associated comment found right above):

typedef struct {
  double length;
  unsigned char nPlaced;
  unsigned char path[0];
}


RouteDefinition* Alloc_RouteDefinition()
{
  // NB: The +nBags*sizeof.. trick "expands" the path[0] array in RouteDefinition
  // to the path[nBags] array
  RouteDefinition *def = NULL;
  return (RouteDefinition*) malloc(sizeof(RouteDefinition) + nBags * sizeof(def->path[0]));
}

Why does this work? I gather that the sizeof the char* will resolve to the size of the pointer on the given architecture, but shouldn't it crash and burn while dereferencing a NULL-pointer?

like image 617
Veeg Avatar asked Nov 05 '13 09:11

Veeg


People also ask

Can you dereference a null pointer?

A NULL pointer dereference occurs when the application dereferences a pointer that it expects to be valid, but is NULL, typically causing a crash or exit. NULL pointer dereference issues can occur through a number of flaws, including race conditions, and simple programming omissions.

Does dereferencing a pointer make a copy?

The reason no copy takes place is because a reference is not a machine code level construct. It is a higher level construct and thus is something the compiler uses internally rather than generating specific code for it.

Can you dereference twice?

You dereference it once you get the pointer it was pointing to, dereference it twice you get the object pointed to by the pointer ptr_ptr is pointing to. I really expected this to be a duplicate, but surprisingly it's not. Definitely worth an answer.

What is the problem with dereferencing the null pointer?

In practice, dereferencing a null pointer may result in an attempted read or write from memory that is not mapped, triggering a segmentation fault or memory access violation. This may manifest itself as a program crash, or be transformed into a software exception that can be caught by program code.


2 Answers

Why does this work?

This works because sizeof is a compile time construct, with the exception of variable length arrays is not evaluated at all. If we look at the C99 draft standard section 6.5.3.4 The sizeof operator paragraph 2 says(emphasis mine):

[...] The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.

we also see the following example in paragraph 5 which confirms this:

double *dp = alloc(sizeof *dp);
       ^^^                ^
                          |                                 
                          This is not the use of uninitialized pointer 

At compile time the type of the expression with be determined in order to compute the result. We can further demonstrate this with the following example:

int x = 0 ;
printf("%zu\n", sizeof( x++ ));

which won't increment x, which is pretty neat.

Update

As I note in my answer to Why does sizeof(x++) not increment x? there is an exception to sizeof being a compile time operation and that is when it's operand is a variable length array(VLA). Although I did not previously point it out the quote from 6.5.3.4 above does say this.

Although in C11 as opposed to C99 it is unspecified whether sizeof is evaluated or not in this case.

Also, note there is a C++ version of this quesiton: Does not evaluating the expression to which sizeof is applied make it legal to dereference a null or invalid pointer inside sizeof in C++?.

like image 131
Shafik Yaghmour Avatar answered Oct 21 '22 13:10

Shafik Yaghmour


The sizeof operator is a pure compile-time operation. Nothing is done runtime, which is why it works fine.

By the way, the path member is not actually a pointer, so it can't technically be NULL.

like image 10
Some programmer dude Avatar answered Oct 21 '22 13:10

Some programmer dude