tags:

views:

90

answers:

4

When compiled by gcc and then run, the code

    int *p;
    int main() {*p = 1;}

causes a segmentation fault.

Apparently, the memory location contained in p cannot be written to.

Why????

On the other hand,

    int q[];
    int main() {*q = 1;}

runs just fine.

What's going on here??

Why does p contain only read-only memory?

+10  A: 

The first example has a wild (not explicitly initialized) pointer. Since it's not an automatic variable, it is set to 0, which clearly is not memory you own. You can see this by printing it out with:

printf("%p\n", p)

As for the second, C99 §6.9.2 actually gives this as an example:

EXAMPLE 2 If at the end of the translation unit containing

int i[];

the array i still has incomplete type, the implicit initializer causes it to have one element, which is set to zero on program startup.

In general, objects with tentative definition (no initializer) are initialized with 0, which for an array means a 1-element array with element value 0.

Matthew Flaschen
As an ex-C++ developer, I still have to ask the question as to why the *q = 1 works "fine" - luck?
Will A
I think `gcc`'s warning sums it up: `warning: array ‘q’ assumed to have one element` - whether this is valid C, or just `gcc` being generous, I'm not sure.
Thanatos
@Will A: Because the compiler he is using is probably still assigning the array 'q' with some memory or simply a position in memory (with 0 elements) that points to a writable section of memory (where the rest of the global variables are stored). Because the array hasn't actually been given a size, I'd say that this is either undefined behaviour, or the compiler not being compliant (I'm not sure which it is in this case).
Grant Peters
A: 

Your first example causes a segmentation fault because you are dereferencing NULL. You never initialize p with a value, and because it's a global it will be NULL. Thus, you dereference NULL, and boom.

I'm not sure how the second example is valid - gcc notes that it is assuming q to be a 1-element array, which is why that won't blow up.

Thanatos
+3  A: 

*p = 1; causes Segmentation fault because it was not allocated any memory before the assignment.

*q = 1;works because the compiler (gcc 4.2.1 on Mac OS X) warns that q[] is assumed to have one element.

vpit3833
A: 

But it doesn't seem to matter whether p was initialized or not! The following code

   int *p = 1;
   main() {*p = 2;}

still fails!

(Why??)

ManRow
Because you're pointing to address 1, which is also not memory you own. Try instead "int x; int* p = ". That initializes p to point to x.
bstpierre