Newsgroup: it.comp.lang.c
Titolo: [lunghetto] Problema con variabile globale

Buongiorno a tutti.
Sto scrivendo un'applicazione p2p (in ambiente linux) in cui il 
funzionamento si basa su un principio elementare: il client invia una 
richiesta dopo la connect(), e il server aggiunge i dati client all'interno 
di una semplice lista collegata, rappresentata dalla seguente struct:
struct nodo{
    char address[16];
    unsigned int port;
    struct nodo * next;
}
Quello che faccio è dichiarare una variabile globale
struct nodo*P=NULL;
utilizzata dalle funzioni del server.
Il problema è nella fase di riempimento della lista.
ho una funzione del genere (classica):
struct nodo* aggiungi(char* IP, unsigned int port){
    struct nodo* pAux;
    if(P==NULL){
        P=(struct nodo*)malloc(sizeof(struct nodo));
        sprintf(P->address, "%s", IP);
        P->port=port;
        P->next=NULL;
        pAux=P->next;
    }
    else{
        //creazione dei nodi successivi
        //mediante avanzamento di paux
    }
    return P; //ritorno il puntatore in testa alla lista.
}
In realtà, quando questa funzione viene chiamata, P risulta essere *sempre* 
a NULL (e quindi solo il ramo if di aggiungi() viene invocato, con 
conseguente sovrascrittura del solo primo elemento della lista P).
Da che cosa può dipendere?
Grazie mille
Alessio Rocchi 

 funzione e rimane tale anche dopo che esci.
[CUT]
Avevo omesso di scrivere il ramo else solo per il fatto che l'algoritmo è 
classico.
comunque, riprendo l'intera funzione:
struct nodo* aggiungi(char* IP, unsigned int port){
    struct nodo* pAux;
    if(P==NULL){
        P=(struct nodo*)malloc(sizeof(struct nodo));
        sprintf(P->address, "%s", IP);
        P->port=port;
        P->next=NULL;
        pAux=P->next;
    }
    else{
       pAux=(struct nodo*) malloc (sizeof(struct nodo));
       sprintf(pAux->address, "%s", IP);
       pAux->port=port;
       pAux->next=NULL;
       pAux=pAux->next;
   }
    return P; //ritorno il puntatore in testa alla lista.
}
non c'è modo, utilizzando una variabile globale, di mantenerla valorizzata 
mediante un return?
grazie,
Alessio Rocchi 

     return P; //ritorno il puntatore in testa alla lista.
secondo te P è il puntatore in testa alla lista?!?!
alla prima esecuzione (if P==NULL), P -> un oggetto nodo;
alla seconda (if P!=NULL), pAux è un nodo che poi viene
azzerato!!!
 >        pAux->next=NULL;
 >        pAux=pAux->next;
cioè PAux == NULL.
Mi spieghi che concatenamento otterrai mai con questa funzione 
aggiungi()???? non ci sarà MAI nessun collegamento tra P e pAux!!!


Sinceramente non riesco a capire cosa vorresti fare, ma il codice e'
comunque errato in entrambi i rami dell'if...
Ti leggo in italiano quello che fa il tuo codice.
(Se l'avessi fatto tu ti saresti gia' dovuto accorgere dell'errore...)
se P e' nullo (dovrebbe essere tale solo alla prima
invocazione) fa la seguente cosa:
1) alloca un nodo. Ok
2) poni P uguale all'indirizzo di questo nodo. Ok
3) copia i dati nel nodo. Ok ( a parte che basta usare una strcpy invece
della sprintf...)
4) poni a NULL il puntatore next per indicare che
questo e' l'ultimo nodo della lista.
5) poni pAux a NULL, copiandoci il valore P->next che e'
appena statomesso a NULL!!!
Questo e' sbagliato per almeno due motivi. (a) pAux e' una variabile
locale e non globale, quindi l'assegnamento e' inutile, visto che
il valore viene perso alla fine della funzione. Doveva essere globale
anche questo? Se doveva essere globale allora doveva servire per puntare
alla fine della lista, ovvero all'ultimo elemento, cioe' a P e non a
NULL. Quindi in un modo o nell'altro questa ultima istruzione e' sbagliata)
Se invece P non e' nullo, siamo nella situazione in cui P punta
ad un nodo precedentemenente allocato.
In tal caso fai:
1) allochi un nodo e assegni l'indirizzo alla variable locale pAux. Ok.
2) copi i valori nel nodo appena allocato. Ok
3) poni il puntatore next a NULL, quindi assumo che tu voglia che
questo sia l'ultimo nodo della lista... Ok. forse.
4) poni la variabile locale pAux uguale a NULL (copiandoci il valore
appena assegnato a next). ????
Come detto sopra questo assegnamento non ha senso.
Secondo me dovresti decidere se vuoi fare l'inserimento del nuovo nodo
in cima o in fondo alla lista. Poi scrivere il programma in italiano
sulla carta e poi tradurlo nelle istruzioni corrispondenti.
Se lo vuoi fare in cima ti basta allocare un nuovo nodo,
copiarci la roba, fare in modo che il suo next punti al vecchio P,
e fare in modo che il nuovo P punti al nodo appena allocato.
Se vuoi farlo in coda, allora P dopo la prima volta non cambia.
Ti tieni un altro puntatore globale PLast che punta all'ultimo nodo.
Per aggiungere: allochi un nodo, ci copi la roba, fai in modo
che il nodo puntato da PLast punti come next al nodo appena allocato,
poi aggiorni Plast in modo che punti al nodo nuovo (che avra' next a null).
Naturalment non c'e' nessun bisogno di usare delle variabili
globali.
Basta fare un struct chiamata Lista o qualcosa di simile che
al suo interno contenga le varie informazioni rilevanti, tipo
puntatori alla testa e alla coda, numero di elementi etc.
e poi quando devi fare le operazioni passi anche un puntatore
alla variabile Lista sulla quale vuoi lavorare.
In questo modo puoi anche gestire piu' liste se ti servono
in modo pulito.
ciao,
g.

 il valore viene perso alla fine della funzione. 
Ahi ahi...attenzione :-)
pAux non viene perso all'uscita della funzione...è allocato dinamicamente;
Però ho capito cosa intendi dire: che non viene legato a P e quindi
è memoria allocata che all'uscita della funzione si va a far benedire 
;-) o meglio vaga negli oscuri meandri!!!
Chi ha iniziato questo thread, mi sa che fa un'pò di confusione con i
puntatori, quindi è meglio usare parole "più precise".

AlterX wrote:

Infatti sono stato preciso. Rileggi la mia frase e il codice.
Parlando del primo ramo dell'if,
ho detto che l'ultimo valore assegnato a pAux viene perso alla fine della
funzione. E' esattamente quello che accade.
pAux e' un puntatore. Il suo valore e' un indirizzo che viene perso
all'uscita dalla funzione. In questo caso poi valeva NULL, perche'
nel primo ramo dell'if non gli veniva assegnato nulla, dinamicamente.
E' nel secondo ramo dell'if che avviene l'assegnamento dinamico
di un valore al puntatore pAux. Anche in questo caso, all'uscita
della funzione viene perso il valore (indirizzo di memoria) di pAux.
Tuttavia, questa perdita avviene ancora prima, perche' incomprensibilmente
nel codice si pone pAux->next=NULL; pAux=pAux->next; e quindi
si pone pAux a NULL, togliendo ogni possibilita' di accedere al nodo
appena allocato.
ciao,
g.

 
Scusami, ma sei tu che stai usando una terminologia imprecisa: non ha alcun 
senso dire che pAux è "allocato dinamicamente". pAux è una variabile locale 
a cui viene assegnato l'indirizzo di un blocco di memoria allocato 
dinamicamente.
Max

 
Opss...scusa non ho letto tutto il testo...