I'm new to C++ and just trying to get a hang of it. It generally seems not too bad, but I stumbled upon this weird/pathological segfaulting behavior:
int main () {
int* b;
*b = 27;
int c = *b;
cout << "c points to " << c << endl; //OK
printf( "b points to %d\n", *b); //OK
// cout << "b points to " << (*b) << endl; - Not OK: segfaults!
return 0;
}
This program, as given, produces what you'd expect:
c points to 27
b points to 27
On the other hand, if you uncomment the second-to-last line, you get a program that crashes (seg-fault) in runtime. Why? This is a valid pointer.
The pointer is valid in as much it's got a value. But the memory is probably not. It's your OS telling you that you are touching memory which isn't yours.
I'm frankly surprised it doesn't crash earlier than that.
Here's why:
Where does
b
point? It might be somewhere valid, or somewhere totally off-limits. You can usually bet on the latter.Here's a better way to do what you want.
Now
b
points to the location on the stack whereb1
s value is stored.Update 3
My answer to Where exactly does C++ standard say dereferencing an uninitialized pointer is undefined behavior? gives a much better answer to why using an uninitialized pointer is undefined behavior. The basic logic from the C++ draft standard, section
24.2
Iterator requirements, specifically section24.2.1
In general paragraph 5 and 10 which respectively say (emphasis mine):Update 2
This was originally an answer to a C question with nearly identical circumstances but the original question I answered was merged with this one. I am updating my answer to include an answer specific to the new question and to the C++ draft standard.
b
has not be initialized and therefore it's value is indeterminate but you used indirection onb
which is undefined behavior.One possible simple fix would be to assign
b
to the address of an existing variable, for example:Another option would have been to use dynamic allocation via new.
For completeness sake we can see this is undefined behavior by going to the draft C++ standard section
5.3.1
Unary operators paragraph 1 which says(emphasis mine):and if we then go to section
3.10
Lvalues and rvalues paragraph 1 says(emphasis mine):but
b
does not point to a valid object.Original Answer
You did not allocate any memory to
f
norb
but you used indirection on both which is undefined behavior.Update
It is worth noting that cranking up the warning levels should have indicated this was a problem, for example using
gcc -Wall
gives me the following warning for this code:The simplest fix would be to assign
f
to point to a valid object like so:Another options would be to use dynamic allocation, if you don't have a handy reference the C FAQ is not a bad place to start.
for completeness sake, if we look at the C99 draft standard Annex
J.2
Undefined behavior paragraph 1 says:and includes the following bullet:
The value of
f
andb
are both automatic variables and are indeterminate since they are not initialized.It is not clear from reading the referenced sections which statement makes it undefined but section
6.5.2.5
Compound literals paragraph 17 which is part of normative text has an example with the following text which uses the same language and says:In the C11 draft standard the paragraph is 16.
int* b
points to an unknown memory address because it wasn't initialized. If you initialized it to whatever null pointer value exists for your compiler (0
until C++11,nullptr
in C++11 and newer), you'd most certainly get a segfault earlier. The problem lies in the fact that you allocated space for the pointer but not the data it points to. If you instead did this:Things would work because
int* b
refers to a memory location that is accessible by your program (since the memory is actually a part of your program).If you leave a pointer uninitialized or assign a null value to it, you can't use it until it points to a memory address that you KNOW you can access. For example, using dynamic allocation with the
new
operator will reserve memory for the data for you:This is because
f
is a pointer and it need to be allocated some memory for it.General rule: initialize variable before using it
char* f;
is a variable.*f
is usage of this variable. Like any variable,f
must be initialized before usage.