2012-01-30 15 views
5

Tutaj chcę utworzyć dynamicznie pamięć. tutaj nie znam wielkości wyjściowej i chcę wydrukować ostatnie końcowe wyjście po pętli while.Usterka segmentacji w Realloc

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

void main() { 

    char *sdpCommand = "sdptool browse 04:18:0F:B1:48:B5"; 

    FILE *fp; 
    fp = popen(sdpCommand, "r"); 

    char *results = 0; 
    if (fp == NULL) { 
     printf("Failed to run command\n"); 
     return; 
    } 

    char* buffer = malloc(514); 
    while (fgets(buffer, strlen(buffer) - 1, fp) != NULL) { 
     realloc(results, strlen(results) + strlen(buffer)); 
     memcpy(results + strlen(results), buffer, strlen(buffer)); 
    } 
    printf("Output ::: %s", results); 

    /* close */ 
    pclose(fp); 
    sleep(1); 

} 

Odpowiedz

11

Istnieją dwa główne problemy:

  1. realloc()powraca nowy adres:

    new_results = realloc(results, ...); 
    if (new_results != NULL) { 
        results = new_results; 
    } else { 
        /* handle reallocation failure, `results' is still valid */ 
    } 
    
  2. sizeof() nie jest dobrym sposobem, aby dowiedzieć się o wielkości results i z buffer. Po prostu zwróci rozmiar wskaźnika . W przypadku results prawdopodobnie chcesz samodzielnie śledzić przydzielony rozmiar. Dla buffer prawdopodobnie szukasz strlen().

Po rozwiązać powyższe, należy upewnić się, że results kończy jako ważnego znakiem NUL łańcucha. Jest to konieczne, aby printf() działał poprawnie.

+2

... lub 'NULL' jeśli przydział nie powiodło. – unwind

+0

Aby rozwinąć, 'sizeof (wyniki)' i 'sizeof (buffer)' zwracają rozmiar wskaźników, które są znane podczas kompilacji. W standardzie C nie ma sposobu na zapytanie o wielkość dynamicznie przydzielanego bloku pamięci. Dlatego musisz pamiętać, ile przeznaczyłeś. –

+0

Czy możesz mi powiedzieć, gdzie muszę to zmienić, a mój kod działa poprawnie? – user1089679

2

Twój kod po prostu ślepo podąża naprzód, pozornie napisany zgodnie z paradygmatem "kompiluje, to musi działać". Przykro mi, jeśli to zabrzmi ostro, to nie jest komentarz do ciebie osobiście, oczywiście.

Musisz naprawdę wyglądać w dokumentacji interfejsu API: s próbujesz użyć i przeanalizować, czy użycie ma sens.

Nie można zignorować wartości zwracanej z realloc(), w jaki sposób uzyskać nowo przydzieloną pamięć? Nie można zmienić istniejącego wskaźnika, ponieważ przekazujesz go według wartości.

Sposób dynamiczna tablica zazwyczaj potrzebuje do pracy jest, aby śledzić z trzech rzeczy:

  • adres bazowy bieżącego zestawu za
  • liczba elementów (bajtów, w danym przypadku), że tablica posiadanych teraz
  • liczba elementów tablicy można przytrzymać, maksimum (wcześniej musi rosnąć)

Podczas dołączania n nowe elementy, sprawdzasz, czy powoduje to przepełnienie liczby elementów, więc staje się większe niż maksimum. To niedozwolone, więc w takim przypadku musisz ponownie przydzielić tablicę podstawową, aby nowe dane pasowały, i (oczywiście) zaktualizować odpowiednio stan tablicy.

1

realloc (wyniki, sizeof (wyniki) + sizeof (bufor));

Ta linia może być problemem.

  1. realloc() zwraca nowy adres przydzielony o określonej wielkości i nie ma gwarancji, że będzie to ten sam adres wskaźnik przedtem; Powinieneś zawsze zmieniać przypisanie wskaźnika:

    ptr = realloc (ptr, nowy rozmiar);

  2. sizeof() nie zwróci dynamicznego przydzielonego rozmiaru wskaźnika. W tym przypadku najprawdopodobniej powracają zawsze: sizeof(results) i sizeof(buffer) 8. Możesz zastąpić:

    wyniki = ponowne wysłanie (wyniki, ctr * 514);
    Gdzie ctr to short zainicjalizowane na wartość 0 przed while i liczenie liczby iteracji.

  3. Ponieważ bufor jest zawsze 514 dlaczego nie można zmniejszyć obciążenie przez redifining go:

    buforze char [514];

    Pozdrawiam

+0

Przypisanie 0 do wskaźnika jest całkowicie poprawne, a standard wymaga, aby kompilator przypisywał w tym przypadku 'NULL' do wskaźnika. –

+0

Stoję poprawione. Dziękuję Ci – whitelionV