1
struct x {
  int *u;
};

struct y {
  struct x *z;
};

int main()
{
  static y b;
  static int g=7;
  b.z->u=&g;
}

The statement b.z->u=&g gives a segmentation error. If I remove the static in front of int g:

int g=7;
b.z->u=&g;  

The code executes properly.

Alex
  • 14,973
  • 13
  • 59
  • 94
karan
  • 313
  • 2
  • 3
  • 20
  • Could not understand the reason why it happens this way.Also is there any alternative for the above allocation.. – karan Sep 16 '11 at 18:36
  • 2
    Every answer at this time states that static allocation of b results in b.z set to an undefined value. In fact, static guarantees zero-initialized memory, so b.z is NULL. If you remove the keyword static, then you get an even worse bug wherein b.z points to some random place in memory, perhaps the place argv is stored, etc. – Heath Hunnicutt Sep 16 '11 at 18:44
  • 1
    @Heath Hunnicutt: Not true. Firstly, my answer and the comments stated virtually from the very beginning that the pointer is null. Other answers did too. Secondly, the OP explicitly asked in one of the comments about a non-static version of the same thing. – AnT stands with Russia Sep 16 '11 at 21:54

4 Answers4

2

Because b.z hasn't been set to point anywhere useful. It's currently just a NULL pointer.*

You need to do something along the lines of:

b.z = malloc(sizeof(*b.z));

first (i.e. create an actual object).

Remember to free this at some point.


* Note that it's only NULL because b is declared as static. If b were non-static, it would be pointing at somewhere random in memory.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
  • Looks like someone didn't like the question and wanted to ding everyone who answered it. I guess there was nothing good on Youtube today. – Tim Post Sep 18 '11 at 20:48
2

b.z is not yet initialized. You initialize b with:

static y b;

but its member field z is still a null pointer (pointing so some random location). So accessing its member u results in an segmentation error as you are accessing some random memory.

I suppose that like this should work (did not try):

static y b;
static x c;
static int g=7;
b.z = &c;
b.z->u=&g;

Why your second example works, I do not know. I suspect it is due to 'luck'...

Veger
  • 37,240
  • 11
  • 105
  • 116
1

It will give you a segmentation error, because what you're doing is undefined behavior. You're accessing the z pointer of the structure without initializing it (that is, without giving it a memory space to point to). The fact that it is not giving you a segmentation error in the case the variable is not static is not important, as the whole access to an uninitialized pointer is wrong.

Diego Sevilla
  • 28,636
  • 4
  • 59
  • 87
  • 1
    Strictly speaking, since `b` is declared `static`, it is guaranteed to be zero-initialized. `b.z` is guaranteed to be a null pointer. The behavior is still undefined, of course. – AnT stands with Russia Sep 16 '11 at 18:43
1

You never allocated memory for your b.z. Your b.z contains an uninitialized garbage value, which is why trying to dereference b.z (in b.z->u) causes a segmentation fault.

P.S. You declared your objects static, which means that b.z initially contains a null value (not an "uninitialized garbage value" as I stated above). Nevertheless, dereferencing a null pointer is also undefined.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • 1
    @karan: What "nonstatic allocation"? If you remove `static`? No, it doesn't "work". If it doesn't crash, it is simply because you got lucky somehow and the garbage value ended up pointing to some writable memory, which you subsequently destroy. – AnT stands with Russia Sep 16 '11 at 18:42
  • 1
    @karan - No. It may *appear* to work, but the reason is subtle and the truth is that your code has a terrible bug because b.z is never initialized. Oli's answer is great. The reason static clarifies your bug is that static guarantees zero-initialized variables. That sets b.z as a NULL pointer and you get a nice, deterministic crash. When b is allocated non-static, it receives contents from whatever was on the stack previously. In that case b.z could obtain the value NULL, or some non-pointer value, or some other valid pointer (then using b.z will overwrite the other pointer's memory). – Heath Hunnicutt Sep 16 '11 at 18:43