2015-04-15 12 views
10

Stworzyłem funkcję zaprojektowaną w celu uzyskania informacji od użytkownika. Wymaga to przydzielenia pamięci do zmiennej przechowującej dane wejściowe użytkownika; jednak ta zmienna jest zwracana na końcu funkcji. Jaka jest właściwa metoda zwolnienia przydzielonej pamięci/zwrócenia wartości zmiennej?Właściwy sposób na zwolnienie pamięci zwróconej zmiennej

Oto kod:

char *input = malloc(MAX_SIZE*sizeof(char*)); 
int i = 0; 
char c; 

while((c = getchar()) != '\n' && c != EOF) { 
    input[i++] = c; 
} 

return input; 

powinienem wrócić adres wejścia i wolne to po to służy?

Ciekawy co do najbardziej odpowiedniej metody na uwolnienie zmiennej wejściowej.

+0

Jeśli "malloc", w końcu ktoś będzie musiał "za darmo", czy to ty w innym api lub dzwoniącym. Powiązane, jeśli obsługiwane na platformach docelowych, ['getline'] (http://pubs.opengroup.org/stage7tc1/functions/getdelim.html), funkcja biblioteczna dodana do POSIX.1-2008, wydaje się * prawie * robić to, co próbujesz zaimplementować. Nadal wymaga, aby wywołujący ostatecznie "zwolnił" wszelkie zwrócone alokacje, ale także zapewnia semantykę ponownego użycia, gdzie twój kod * nie *. W zależności od przeznaczenia i platformy docelowej, może być warte rozważenia. – WhozCraig

Odpowiedz

11

To całkiem proste, jeśli przejdziesz na free(), ten sam wskaźnik zwrócony przez malloc() jest w porządku.

Na przykład

char *readInput(size_t size) 
{ 
    char *input; 
    int chr; 
    input = malloc(size + 1); 
    if (input == NULL) 
     return NULL; 
    while ((i < size) && ((chr = getchar()) != '\n') && (chr != EOF)) 
     input[i++] = chr; 
    input[size] = '\0'; /* nul terminate the array, so it can be a string */ 
    return input; 
} 

int main(void) 
    { 
    char *input; 
    input = readInput(100); 
    if (input == NULL) 
     return -1; 
    printf("input: %s\n", input); 
    /* now you can free it */ 
    free(input); 
    return 0; 
    } 

Co nigdy nie powinno się robić coś takiego jak

free(input + n); 

ponieważ input + n nie jest powrót pointer przez malloc().

Ale kod, ma inne problemy, należy zadbać o

  1. Jesteś alokacji przestrzeni dla MAX_SIZEchar s więc należy pomnożyć przez sizeof(char) która 1 zamiast sizeof(char *) które mogłyby przeznaczyć MAX_SIZE wskazówek, a także możesz zamiast tego uczynić MAX_SIZE parametr funkcji, ponieważ jeśli alokujesz stały bufor, możesz zdefiniować tablicę w main() o rozmiarze MAX_SIZE, jak char input[MAX_SIZE], i przekazać ją do readInput() jako parametr r, unikając w ten sposób malloc() i free().

  2. Przydzielasz tyle miejsca, ale nie zapobiegniesz przepełnieniu w pętli while, powinieneś sprawdzić, czy i < MAX_SIZE.

+0

Nie może używać tablic lokalnych, ponieważ po powrocie i zniszczeniu ramki stosu tej funkcji nie będzie możliwości zagwarantowania, że ​​tablica będzie nienaruszona. Kompilator wyświetli ostrzeżenie: "funkcja zwraca adres zmiennej lokalnej [-WRowrót-local-addr]". Poza tym dobra odpowiedź. –

+1

@EnzoFerber Miałem na myśli przekazać tablicę do funkcji i wypełnić ją tam, wiem, że nie możesz zwrócić lokalnej tablicy. Myślę, że muszę to wyjaśnić. –

4

można napisać funkcję z typ zwracany char*, powrót input, i poprosić użytkownika zadzwonić free raz ich zrobić z danymi.

Można również poprosić użytkownika o przekazanie we właściwym rozmiarze bufora wraz z limitem rozmiaru bufora i zwrócenie liczby znaków zapisanych w buforze.

-1

To klasyczny przypadek. Funkcja pamięci mallocs dla jej wyniku, wywołujący musi zwolnić zwróconą wartość. Przechodzisz teraz na cienki lód przecieków pamięci. 2 powody

Pierwsza; nie ma sposobu, aby przekazać wolne wymagania w sposób egzekwowalny (np. kompilator lub środowisko wykonawcze nie może ci pomóc - kontrast z określeniem, jakie typy argumentów są).Musisz go gdzieś udokumentować i mieć nadzieję, że osoba dzwoniąca przeczytała twoje dokumenty.

Po drugie: nawet jeśli osoba dzwoniąca wie o uwolnieniu wyniku, może popełnić błąd, zostanie podjęta pewna ścieżka błędu, która nie zwalnia pamięci. Nie powoduje to natychmiastowego błędu, wszystko działa, ale po trzech tygodniach aplikacja się zawiesza po wyczerpaniu pamięci.

Dlatego właśnie wiele "nowoczesnych" języków koncentruje się na tym temacie, C++ smart pointers, Java, C#, etc zbieranie śmieci, ...

Powiązane problemy