Pointer initialisation gives segmentation fault

23,742

Solution 1

CASE .1

int *a; /* pointer variable declaration */

int b; /* actual variable declaration */

*a=11;//Not valid means you are not owner of the address where a now pointing it is unknown and accessing this will segfault/

a=&b;/* store address of b in pointer variable*/

This is going to be segmentation fault because the address you are using is not a valid address and there you are storing 11 which is illegal.

                               b
      +-------+            +--------+
      |       +            |   11   |
      |Unknown|            |        |
      +---+---+            +---+----+
          |                    |
          |                    |
          +                    +
          a                    a
CASE .2

int *a; /* pointer variable declaration */

int b; /* actual variable declaration */

a=&b;/* store address of b in pointer variable*/

*a=11;

Now its working fine because the address of b is valid an there you are storing 11 which is legal.

Also above cases are not correct way of pointer declaration

  int *a  = NUll;
  a = malloc(sizeof(int));
  *a=5;
  free(a);//must

or

 int *a  = NUll;
 int b;
 a = &b;
 *a=5;

This will remove segmentation fault many times which is hard to find .

Solution 2

int *a; // a pointer variable that can hold a memory address of a integer value.

In case 1,

  *a = 10; // here you have asigned 10 to unknown memory address;

It shows segmentation fault because of assigning value to a memory address that is not defined. Undefined behaviour.

In case 2,

a=&b; // assigning a proper memory address to a.
*a=11;// assigning value to that address

Consider this example:

#include<stdio.h>
int main()
{
   int *a,b=10;
   printf("\n%d",b);
   a=&b;
   *a=100;
   printf("-->%d",b);
}

Output: 10-->100

Here this is how it works.

         b        // name
     ----------
     +   10   +   // value
     ---------- 
        4000      // address 

Asuuming memory location of b is 4000.

a=&b => a=4000;
*a=100 => *(4000)=100 => valueat(4000) => 100

After manipulation it looks like this.

         b        // name
     ----------
     +  100   +   // value
     ---------- 
        4000      // address 

Solution 3

One line: First code you are dereferencing uninitialized pointer which exhibits undefined behaviour, and in the second code you are dereferencing initialized pointer which will give access to the value at the address.

A bit of explanation:

First you need to realize that a pointer is nothing but an integer, an with the *var we tell the compiler that we will be using the content of the variable var (the integer in it) as an address to fetch the value in that address. If there is **var similarly we tell the compiler that we will first use the stored value of the variable var to fetch the value at the address and again use this fetched value as an address and fetch the value stored in it.

Therefore in your first declaration it is:

           +----------+        +----------+
           |  garbage |        |  garbage |
           +----------+        +----------+
           |    a     |        |    b     |
           +----------+        +----------+
           |  addr1   |        |  addr2   |
           +----------+        +----------+

Then you try to use the value stored in a as an address. a contains garbage, it can be any value, but you do not have access to any address location. Therefore the next moment when you do *a it will use the stored value in a as an address. Because the stored value can be anything, anything can happen.

If you have permission to access the location , the code will continue to execute without a segmentation fault. If the address happens to be an address from the heap book-keeping structure, or other memory area which your code allocated from heap or stack then when you do *a = 10 it will simply wipe off the existing value with 10 in that location. This can lead to undefined behaviour as now you have changed something without the knowledge of the context having the actual authority of the memory. If you don't have permission to the memory, you simply get a segmentation fault. This is called dereferencing of an uninitialized pointer.

Next statement you do a = &b which just assigns the address of b in a. This doesn't help, because the previous line has dereferenced an uninitialized pointer.

Next code you have something like this after the third statement:

           +----------+        +----------+
           |  addr2   |---+    |  garbage |
           +----------+   |    +----------+
           |    a     |   +--> |    b     |
           +----------+        +----------+
           |  addr1   |        |  addr2   |
           +----------+        +----------+

The third statement assigns the address of b into a. Before that a is not dereferenced, therefore the garbage value stored in a before the initialization is never used as an address. Now when you assign a valid address of your knowledge into a, dereferencing a now will give you access to the value pointed to by a.

Extending the answer, you need to keep an eye that, even if you have assigned a valid address to a pointer, you have to make sure at the time of dereferencing the pointer the lifetime of the address pointed to by the pointer has not expired. For example returning local variable.

int foo (void)
{
  int a = 50;
  return &a;  //Address is valid
}//After this `a' is destroyed (lifetime finishes), accessing this address
 //results in undefined behaviour

int main (void)
{
  int *v = foo ();
  *v = 50; //Incorrect, contents of `v' has expired lifetime.
  return 0;
}

Same in the case of accessing freed memory location from heap.

int main (void)
{
  char *a = malloc (1);
  *a = 'A'; //Works fine, because we have allocated memory
  free (a); //Freeing allocated memory
  *a = 'B'; //Undefined behaviour, we have already freed 
            //memory, it's not for us now.
  return 0;
}

Solution 4

In the first case you have declared a pointer but you have not assigned the address to which it has to point hence the pointer would have contained an address that would have belonged to another process in the system (or it would have contained an junk value which is not an address at all or it would have contained an null which can't be an memory address)hence operating system sends an signal to prevent invalid memory operation and hence an segmentation fault occurs.

In the second case you are assigning the address of the variable which has to be updated to the pointer and storing the value which is the correct way of doing and hence there's no segmentation fault.

Solution 5

int a stores a random integer value. So saying by saying *a, you might be accessing a memory location that is out of bounds or invalid. So it is a seg fault.

Share:
23,742
EnterKEY
Author by

EnterKEY

Updated on July 09, 2022

Comments

  • EnterKEY
    EnterKEY almost 2 years

    I wrote a C program as follows:

    CASE 1

    int *a; /* pointer variable declaration */
    
    int b; /* actual variable declaration */
    
    *a=11;
    
    a=&b;/* store address of b in pointer variable*/
    

    It gives a segmentation fault when running the program.

    I changed the code as follows:

    CASE 2

    int *a; /* pointer variable declaration */
    
    int b; /* actual variable declaration */
    
    a=&b;/* store address of b in pointer variable*/
    
    *a=11;
    

    Now it's working fine.

    If anyone knows please explain why it is giving a segmentation fault in CASE 1.