2010-10-08 16 views
6

ja nie rozumiem, dlaczego w tym kodzie, wezwanie do „wolnego” przyczyną usterki segmentacji:Malloc, wolny i segmentacja winy

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

char *char_arr_allocator(int length); 

int main(int argc, char* argv[0]){ 

    char* stringa = NULL; 
    stringa = char_arr_allocator(100); 
    printf("stringa address: %p\n", stringa); // same address as "arr" 
    printf("stringa: %s\n",stringa); 
    //free(stringa); 

    return 0; 
} 

char *char_arr_allocator(int length) { 
    char *arr; 
    arr = malloc(length*sizeof(char)); 
    arr = "xxxxxxx"; 
    printf("arr address: %p\n", arr); // same address as "stringa" 
    return arr; 
} 

Czy ktoś może mi to wyjaśnić?

Dzięki Segolas

+0

Również spojrzeć na http://www.hpl.hp.com/personal/Hans_Boehm/gc/ To naprawdę miłe. –

Odpowiedz

14

Jesteś przydzielania pamięci za pomocą malloc poprawnie:

arr = malloc(length*sizeof(char)); 

wtedy zrobić:

arr = "xxxxxxx"; 

spowoduje arr punkt na adres napisu dosłownym "xxxxxxx", przecieka twoja pamięć. A także wywołanie free na adres literału ciągu prowadzi do niezdefiniowanego zachowania.

Jeśli chcesz kopii napisu do użycia pamięci przydzielonej strcpy jak:

strcpy(arr,"xxxxxxx"); 
+1

Masz rację w części UB: Wywołanie 'free' z dowolną wartością wskaźnika (inną niż' NULL') nie z 'malloc' lub' realloc' daje niezdefiniowane zachowanie. – schot

2

Trzecia linia char_arr_allocator() wymazuje swój wynik malloc() i zastępuje ją kawałkiem pamięci statycznej na stronie danych. Dzwonienie pod numer free() w tym temacie.

Użyj polecenia str[n]cpy(), aby skopiować zamiast tego tekst literału do bufora.

2

Kiedy piszesz stały ciąg w C, taki jak "xxxxxx", to co się dzieje, jest to, że ten ciąg idzie bezpośrednio do pliku wykonywalnego. Gdy odwołasz się do niego w swoim źródle, zostanie on zastąpiony wskaźnikiem do tej pamięci. Więc można odczytać linię

arr = "xxxxxxx"; 

leczenia arr jako numer jak coś takiego:

arr = 12345678; 

Gdzie ta liczba jest adres. malloc zwrócił inny adres, a Ty go wyrzuciłeś, gdy przypisałeś nowy adres do arr. Dostajesz segfault, ponieważ próbujesz uwolnić stały ciąg, który jest bezpośrednio w twoim pliku wykonywalnym - nigdy go nie przydzieliłeś.

0

Ustawiasz arr na wartość zwracaną malloc(), która jest prawidłowa. Ale następnie zmieniasz go tak, by wskazywał stałą ciągową "xxxxxxx". Tak więc, wywołując free(), prosi się środowisko wykonawcze, aby zwolnił stałą łańcuchową, co powoduje błąd seg.