Home > Software design >  Reassigning null pointers
Reassigning null pointers

Time:02-02

Can a null pointer be reused? If yes, under what conditions?

More specifically, can anyone tell what happens with this piece of code?

int *p = 0;
p = (int*)malloc(sizeof(int));

If it's problematic - why? And what is the correct way to do it?

EDIT: I know it's not necessary to do it like that. I'm asking what happens in order to understand the way pointers work in C.

CodePudding user response:

Can a null pointer be re-used?

Yes

if yes, under what conditions?

Always

Your question is actually equivalent to ask when it's ok to reuse an int that has been set to zero, or any other value for that matter. What you need to know is that you cannot undo an assignment, so whatever value the pointer contains will be lost. This is the only direct consequence of reassigning a pointer, null or not null. Any problems will be a consequence of no longer having access the previous value. The reassignment itself is always fine, provided it's done properly. See below.

There are basically two common problems related to this when it comes to pointers.

  1. Dangling pointers. This will happen after you call free on a pointer. It will also happen if the object the pointer is pointing at goes out of scope. A dangling pointer contains garbage, and it's undefined behavior to dereference it.

  2. Memory leaks. If you have allocated memory with malloc or similar to a pointer p and then reassign the pointer, you may lose the ability to free the allocated memory.

But it is always legal to reassign a pointer. What value it contains does not affect that. Consider this code:

...
int *p;
...
p = x;

If this is ok or not will entirely depend on x. Both it's type and value and if it is initialized or not.

More specifically, can anyone tell what happens with this piece of code?

It does work. But I have a few remarks.

  1. It's not necessary to initialize the pointer to null before assigning. Some say it's a good habit. Others say it's bad. There are pros and cons and depends on the situation. I personally think it's bad1 to always2 use it.
    1 In short, my argument is that if null initialization solves a problem, then you might have a much bigger problem in your design that the initialization will not solve, but only hide.
    2 There are valid use cases. Use it in those cases, but make sure you understand why you're doing it.

  2. There's no need to cast the result from malloc. Again, some say it's good. Some say it's bad. I think it's bad, unless you want to compile the C code with a C compiler.

  3. Don't use sizeof(int). Use sizeof *p instead.

See Do I cast the result of malloc? to read about 2 and 3.

I'd write your code as

int *p = malloc(sizeof *p);
if(!p) {
    // Handle error
}

CodePudding user response:

This declaration

int *p = 0;

declares the variable p that is initialized by a null pointer constant.

As any other variable that is not qualified the variable p can be reassigned with a new value as for example

p = (int*)malloc(sizeof(int));

Note: in C you can also just write

p = malloc( sizeof( int ) );

You could not reassigned the variable if it was declared with the qualifier const like

int * const p = 0;

Here is a simple demonstration program

#include <stdio.h>
#include <stdlib.h>

int main( void )
{
    int *p = 0;

    p = malloc( sizeof( int ) );

    if ( p != NULL )
    {
        *p = 10;
        printf( "*p = %d\n", *p );
    }

    free( p );

    int x = 20;

    p = &x;

    printf( "*p = %d\n", *p );
}

Pay attention to that you may call the function free for a null pointer.

CodePudding user response:

Any normal (read/write) pointer can be assigned a new value at any time without problems. A null pointer is simply a pointer pointing at a somewhat well-defined "nowhere". It is generally considered good practice to initialize all pointers to null for that reason. Your code isn't problematic but good practice.

Take your specific example: since you initialize p to null, it will now be possible to write a clean-up code such as

free(p);
p=NULL;

This clean-up code can be called regardless of if malloc was called or not, since passing a null pointer to free is well-defined as "no operation".

This in turn enables the possibility to write an initializing function which can be called multiple times, regardless of if p points at valid memory or not. It would simply clean up the previous use before calling malloc.

What you can't do is to re-assign a pointer pointing at the result of malloc, or you lose the reference to that allocated memory and can't free() it. That creates a memory leak.

CodePudding user response:

Pointers behave exactly the same as any other object.

If you have an integer variable:

int x = 0;

would you ask if you can "reuse" it and assign another value?

  •  Tags:  
  • Related