Salve a tutti, sono qui con uno dei miei soliti dilemmi...

Allora, implementando un albero binario bilanciato
avevo scritto una funzione che mi rimuovesse un nodo, memorizzasse
il suo indirizzo in un puntatore a puntatore passato come parametro
e restituisse il suo nodo sinistro. Il problema è che questa funzione
mi causava un bel SIGSEGV al suo ritorno poichè utilizzavo direttamente il
valore restituito. Ora io ho risolto però vorrei capire se questo
è un bug del mio compilatore o se è una cosa normale.
Faccio un esempio per spiegare. Ecco una funzione che fa piu
o meno quello che faceva la mia:

codice:
#include <stdlib.h>

struct node
{
  struct node *left, *right;
  void *data;
};

/* Salva un nodo in *node e ne restituisce un'altro */
struct node *sigsegv(struct node **node)
{
  struct node *__r;
  struct node *__n;

  /* Creo due nodi sullo heap */

  __n = malloc(sizeof(struct node));
  __n->left = NULL;
  __n->right = NULL;
  __n->data = NULL;

  __r = malloc(sizeof(struct node));
  __r->left = NULL;
  __r->right = NULL;
  __r->data = NULL;

  /* Mette l'indirizzo di __n in *node */
  *node = __n;

  /* Restituisce __r */
  return __r;
}
Ok ora la funzione main che utilizza la funzione definita,
occhio alla chiamata:

codice:
int main( )
{
  struct node *n = NULL;
  
  /*** In una chiamata alloca n e setta n->right ***/
  n->right = sigsegv(&n);
  
  return 0;
}
Esecuzione:

codice:
$ ./a.out
Segmentation fault
E subito il debugger:

codice:
$ gdb a.out
GNU gdb 6.3
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
...
(gdb) break main
Breakpoint 1 at 0x80483ee: file testptr.c, line 28.
(gdb) run
Starting program: /home/._/a.out
(gdb) step
30        n->right = sigsegv(&n);
(gdb) step
sigsegv (node=0xbfa40b50) at testptr.c:14
14        __n = malloc(sizeof(struct node));
(gdb) step
15        __n->right = NULL;
(gdb) step
16        __n->data = NULL;
(gdb) step
18        __r = malloc(sizeof(struct node));
(gdb) step
19        __r->right = NULL;
(gdb) step
20        __r->data = NULL;
(gdb) step
22        *node = __n;
(gdb) step
23        return __r;
(gdb) print __r
$1 = (struct node *) 0x804a060
(gdb) print *__r
$2 = {right = 0x0, data = 0x0}
(gdb) print __n
$3 = (struct node *) 0x804a050
(gdb) print *__n
$4 = {right = 0x0, data = 0x0}
(gdb) step
24      }
(gdb) step

Program received signal SIGSEGV, Segmentation fault.
0x08048407 in main () at testptr.c:30
30        n->right = sigsegv(&n);
(gdb)
In parole povere non posso fare n->right = sigsevg(&n)
perchè al momento in cui la funzione ritorna n non è inizializzato.
Ma se viene impostato dentro alla fnzione!?
Ad esempio se io faccio

codice:
...
  struct node *n = NULL, *right = NULL;

  right = sigsegv(&n);
  n->right = right;
...
Funziona perfettamente. Qualcuno mi spiega perchè succede questo!?

Grazie in anticipo! Christian.