2010-03-25 7 views
11

La memoria allocata con malloc non viene mantenuta al di fuori dell'ambito della funzione?

Ciao,

Sono un po 'nuova per la funzione malloc di C, ma da quello che so che dovrebbe memorizzare il valore nel mucchio, in modo da poter fare riferimento a esso con un puntatore da fuori portata originaria . Ho creato un programma di test che dovrebbe farlo ma continuo ad ottenere il valore 0, dopo aver eseguito il programma. Che cosa sto facendo di sbagliato?

int f1(int * b) { 
b = malloc(sizeof(int)); 
*b = 5; 
} 

int main() { 
int * a; 
f1(a); 
printf("%d\n", a); 
return 0; 
} 

risposta

6

La memoria stessa persiste, ma le perdite perché non sta fornendo il puntatore assegnato al chiamante. Inoltre, stai stampando a quando dovresti stampare *a. Infine, non si restituisce un int da f1.

Prova:

void f1(int **b) { 
*b = malloc(sizeof(int)); 
**b = 5; 
} 

int main() { 
int *a; 
f1(&a); 
printf("%d\n", *a); 
free(a); 
return 0; 
} 
0

Il tuo problema è in realtà non relative a malloc, ma piuttosto il fatto che si sta passando il valore del puntatore detiene attualmente, piuttosto che l'indirizzo di esso. Provare quanto segue:

int f1(int ** b) { 
    *b = malloc(sizeof(int)); 
    **b = 5; 
} 

int main() { 
    int * a; 
    f1(&a); 
    printf("%d\n", *a); 
    return 0; 
} 

passando il valore del puntatore come lo siete stati, non c'era alcun modo per il malloc valore creato da memorizzare nella puntatore.

+3

Questo è di nuovo passare per valore. stai passando l'indirizzo di un valore. ** Non vi è alcun passaggio per riferimento in C ** – raj

+0

abbastanza giusto. Aggiornato per essere più accurato in C. – Dusty

0

L'indirizzo int *b viene cancellato quando la funzione restituisce. Per salvarlo, è necessario utilizzare un puntatore di un puntatore

int f1(int ** b) { 
    *b = malloc(sizeof(int)); 
    **b = 5; 
} 
8

Sembra che stai incomprensione una parte fondamentale del funzionamento C - vale a dire che si tratta di un linguaggio 'pass-by-value' . Per sapere su main() della memoria che hai assegnato, devi riaverlo. Il seguente codice ti farà ciò che desideri:

int f1(int **b) 
{ 
    *b = malloc(sizeof(int)); 
    **b = 5; 
} 

int main(int argc, char **argv) 
{ 
    int *a; 
    f1(&a); 
    printf("%d\n", *a); 
    return 0; 
} 

Ci sono un paio di differenze tra questo codice e il tuo; in primo luogo, la firma di f1() è stata modificata, in modo che possa restituire il risultato della chiamata malloc() nel puntatore passato. Successivamente, la chiamata a f1() è stata modificata per passare l'indirizzo di a anziché a stesso: importante se si desidera che sia "compilato" per f1(), per così dire. Infine, lo printf() in main() è stato modificato per stampare il valore puntato anziché il puntatore stesso.

+7

Non riesco a capire perché tutti siano passati direttamente all'utilizzo di un puntatore a un puntatore. Questo è difficilmente il modo migliore per spiegare come farlo a qualcuno che ha problemi con un altro parte fondamentale della lingua Perché non restituire il puntatore da 'f1()'? – caf

+0

@caf, si! è semplice per un principiante per capire.! – raj

+0

Grazie mille per il feedback a tutti! Il mio codice funziona ora. Non posso avere la funzione restituire il puntatore, perché la funzione nel mio progetto attuale sta già restituendo qualcos'altro .. Grazie ancora! –

22

Sì! a è passato per valore modo che l'indicatore b in funzione f1 sarà locale .. o tornare b,

int *f1() { 
    int * b = malloc(sizeof(int)); 
    *b = 5; 
    return b; 
} 

int main() { 
    int * a; 
    a = f1(); 
    printf("%d\n", *a); 
    // keep it clean : 
    free(a); 
    return 0; 
} 

o passare l'indirizzo a s'

int f1(int ** b) { 
    *b = malloc(sizeof(int)); 
    **b = 5; 
} 

int main() { 
    int * a; 
    f1(&a); 
    printf("%d\n", *a); 
    // keep it clean : 
    free(a); 
    return 0; 
} 
5

Consente supponiamo si assegna un valore di NULL a una funzione prima di chiamare f1.Ora il modo in cui viene definita f1 prende il suo argomento (puntatore su un valore int) in base al valore. Quello è b sarà un'altra variabile di tipo int * che sarà un copia di a. Quindi anche b avrà un valore di NULL. Ora in f1 si modifica il valore con b assegnandogli l'indirizzo di memoria assegnato dinamicamente utilizzando malloc. Diciamo che l'indirizzo di memoria è 0x123. Come risultato di questo incarico, b ha cambiato il suo valore da NULL a 0x123 ma a (in main) continua a contenere NULL, perché la modifica di b non cambierà a, in quanto sono due variabili separate. Di conseguenza, quando si ritorna dalla funzione f1 a rimarrà invariato.

Ci sono 2 modi per risolvere questo problema. Si può fare la funzione f1 restituire il valore del b modificato e quindi assegnarlo a un in main e due, è possibile passare l'a indirizzo in modo che eventuali modifiche apportate in f1 interesseranno a in main troppo.

// f1 now returns the value of b. 
int* f1() { 
int *b = malloc(sizeof(int)); 
*b = 5; 
return b; 
} 

int main() { 
int *a = NULL; 
a = f1(); // assign the return value of f1 to a. 
printf("%d\n", *a); // prints 5...not its *a not just a. 
return 0; 
} 

.

// f1 now takes the address of a. 
void f1(int **b) { 
*b = malloc(sizeof(int)); // you are actually altering a indirectly. 
**b = 5; 
} 

int main() { 
int *a = NULL; 
f1(&a); // now pass the address of a to f1. 
printf("%d\n", *a); // prints 5...not its *a not just a. 
return 0; 
}