Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C segmentation fault when passing a NULL pointer despite a conditional telling the function not to run if a NULL parameter is passed?

I have a program which handles an array of strings. One of the methods removes a string from a specified position in said array. The code is as follows:

void RemoveStringAt(char *array[], int pos)
{
    if((array[pos]!=NULL)&&(array!=NULL)&&(pos!=NULL))
    {
        free(array[pos]);
        array[pos]=NULL;
    }
}

One of the specifications of the project was that it should not cause a seg fault when passing a NULL value. Here's what happened when I tried:

 RemoveStringAt(NULL, NULL);

And the output:

Segmentation fault (core dumped)

Why would I be getting a segmentation fault if one of the conditions for even executing the core part of the method is that none of the values passed can be NULL?

like image 875
freelancer05 Avatar asked Nov 30 '22 17:11

freelancer05


2 Answers

Because you are dereferencing a NULL pointer as part of the check:

if((array[pos]!=NULL)...

array is NULL so you cannot do array[pos]. In C the if condition evaluates from left to right so just change your conditional to be like the below. That is, change the ordering so that array[pos] is never evaluated if array is NULL.

if((array!=NULL) && (pos < MAX_POS) && (array[pos]!=NULL))

Note that your original check pos!=NULL is not correct. For serveral reasons. 1. pos is not a pointer so comparing it against NULL is not semantically correct. 2. NULL is usually defined to be 0 and 0 is a valid pos value. So you need to either define a MAX_POS specifying the number of entries in array or better still, pass that in as an explicit parameter to the function.

And finally, after all that, you don't actually even have to have the array[pos]!=NULL check in the conditional if you don't want to. Nothing inside the if block will cause a segv even if array[pos] is NULL as free is defined to accept a NULL parameter.

like image 92
kaylum Avatar answered Dec 06 '22 10:12

kaylum


The problem is with

if((array[pos]!=NULL)&&(array!=NULL)&&(pos!=NULL))

First

if((array[pos]!=NULL)

will be checked and if the array is NULL it will give a segmentation fault. After this condition

(array!=NULL)&&(pos!=NULL))

will be checked.

Your code should be like

void RemoveStringAt(char *array[], int pos)
{
    if((array!=NULL)&& (array[pos]!=NULL))
    {
        free(array[pos]);
        array[pos]=NULL;
    }
}

And there should not be NULL check for pos because NULL is defined to be 0 and 0 is a valid index in array so we should be able to free at 0 index.

like image 25
sanjay Avatar answered Dec 06 '22 09:12

sanjay