Home > front end >  c pointer segfaults without compiler warning, works when previously assigned
c pointer segfaults without compiler warning, works when previously assigned

Time:03-15

I have a difficulties understanding pointers and how/when they fail. So I made a tiny program which creates a pointer, assigns a value to it and then prints that value. Compiles fine with both gcc and clang and does not give any warnings when using the -Wall switch. Why does it segfault and why does it not segfault when I assign a different value to the pointer first? I thought I had initialized the pointer to somewhere. When I just declare the pointer without initialization, then I rightfully get a compiler warning. However, here I do not get a compiler warning, but it still segfaults.

#include<iostream>

int main(){
  int *b = (int*)  12;  //pointer gets initialized, so it points to somewhere
  //int a = 13;   //works fine when uncommenting this and the next line
  //b = &a;
  *b = 11;
  std::cout << "*b = " << *b << "\n";
    return 0;
}

CodePudding user response:

A pointer is a variable that save a memory address.
You "can" have any memory address in your pointer, but trying to read from memory space outside of where your application are allowed to read, will trigger the OS to kill you application with a segfault error.

If you allow me the metaphor:

You can write on a paper the address of any person in your country. But if you try to enter that house without permission, you most probably will get stopped by the police.

Back to code:

int *b = (int*) 123; // ok, you can save what you want.
std::cout << *b << std::endl; // SEGFAULT: you are not allowed to read at 123.

When you uncomment the two lines of code:

int a = 13;
b = &a;

Basically, b is not any-more pointing to that forbidden 123 address, but to the address of a. a is in your own code, and it memory is not forbidden to you, so accessing *b after this is allowed.

Reading at any hard-coded address is not forbidden by C (in fact it is useful in some situations), but your OS may not allow you to mess with that memory.

On the other hand, the compiler is able to detect a variable being used without initialization, and can warn this case. This has nothing to do with raw pointers.

CodePudding user response:

A pointer is a variable to store an address.

int *b = (int*)  12;

This declares b as a pointer to a value of type int, and initializes it with the address 12. Do you know what resides at address 12? No, you don't. Thus, you should not use that address.

*b = 11;

This stores an integer 11 at the address pointed to by the pointer b. However, since pointer b points at address 12, the integer 11 overwrites something at that address (we don't even know what does it overwrite, because we don't know what is there to begin with). This could corrupt heap or stack or program's code or just cause an access violation, anything can happen.

But if you first do this:

b = &a;

Then pointer b now points at the address at which the variable a is stored. Thus, subsequently writing 11 at that address will just overwrite a's value (from 13 to 11), a perfectly valid operation, no problems.

I just need it to point to some location that can hold an int

Indeed, but this is not enough. Not only shall the location be able to hold an int, that location must also be available for your program to store such an int. This means the location needs to be either that of an existing object (e.g., of an existing variable of type int) or a newly allocated memory chunk capable of holding an int. For example:

b = new int;

This will dynamically allocate the memory needed to store an int, and assign the address of the newly allocated memory to the pointer b.

Remember that after you're done with such dynamically allocated memory, you should deallocate it:

delete b;

Otherwise, there will be a memory leak (at least until the whole process exits anyway).

Nowadays, in modern C , there is rarely a need to use raw pointers to manage dynamic memory allocations/deallocations manually. You'd use standard containers and/or smart pointers for that purpose instead.

  • Related