L
Lauri Alanko
The following code crashes on Solaris 10 when compiled without
optimization:
typedef struct Node Node;
struct Node {
int val;
Node *next;
};
int main(void)
{
Node b = { 2, 0 };
Node a = { 1, &b };
a = *(a.next);
return a.val;
}
What happens is that after a has been written to, and a.next has been
set to null, a.next is dereferenced again (for some obscure reason).
Whose fault is this, the programmer's or the compiler's? Initially I
thought that it's the programmer's fault since there are no sequence
points between the access to a.next and the writing to a, but if that
made the code illegal, how about the following ubiquitous idiom:
Node* p = &a;
p = p->next;
Here, too, we both access p and write to p without sequence points in
between. What's the difference, or is there any?
Thanks in advance.
Lauri
optimization:
typedef struct Node Node;
struct Node {
int val;
Node *next;
};
int main(void)
{
Node b = { 2, 0 };
Node a = { 1, &b };
a = *(a.next);
return a.val;
}
What happens is that after a has been written to, and a.next has been
set to null, a.next is dereferenced again (for some obscure reason).
Whose fault is this, the programmer's or the compiler's? Initially I
thought that it's the programmer's fault since there are no sequence
points between the access to a.next and the writing to a, but if that
made the code illegal, how about the following ubiquitous idiom:
Node* p = &a;
p = p->next;
Here, too, we both access p and write to p without sequence points in
between. What's the difference, or is there any?
Thanks in advance.
Lauri