2016-04-22 35 views
6

Mam problemy z ustaleniem, gdzie i dlaczego otrzymuję błąd segmentacji.Błąd segmentacji podczas korzystania z regexec/strtok_r w C

Piszę kod C, który pyta użytkownika, aby wprowadzić wyrażenie regularne i skompilować go, a następnie wprowadzić łańcuch z wieloma zdaniami:

int main(void){ 

    char RegExp[50]; 
    regex_t CompiledRegExp; 
    char *para; 
    char delim[] = ".!?,"; 
    char *sentence; 
    char *ptr1; 

    printf("Enter regular expression: "); 
    fgets(RegExp, 50, stdin); 

if (regcomp(&CompiledRegExp,RegExp,REG_EXTENDED|REG_NOSUB) != 0) {       

    printf("ERROR: Something wrong in the regular expression\n");       

    exit(EXIT_FAILURE);                 

    } 

    printf("\nEnter string: "); 

strtok_r służy podzielić ciąg z jednym z następujące ograniczniki.,?! a następnie otrzymany żeton (zdanie) jest stosowana jako parametr ciąg w regexec funkcji, która przeszukuje go zobaczyć, czy wyrażenie regularne wcześniej skompilowany jest zawarty w Token:

if(fgets(para, 1000, stdin)){ 

    char *ptr = para; 
    sentence = strtok_r(ptr, delim, &ptr1); 

    while(sentence != NULL){ 

     printf("\n%s", sentence); 

     if (regexec(&CompiledRegExp,sentence,(size_t)0,NULL,0) == 0) { 
     printf("\nYes"); 
     } else { 
     printf("\nNo"); 
     } 
     ptr = ptr1; 
     sentence = strtok_r(ptr, delim, &ptr1); 

    } 
    } 
regfree(&CompiledRegExp); 
} 

To pewnie głupie pomyłki jestem ale każda pomoc w zlokalizowaniu przyczyn segfaul byłaby ogromnie doceniona!

EDYCJA:Przeniesiono regfree do bardziej odpowiedniego miejsca. Jednak nadal występuje błąd segfault. Jestem prawie pewien, że ma coś wspólnego z tym, w jaki sposób odczytuje się wyrażenie regularne lub jak jest porównywany w regexec. Clueless jednak.

+0

Co z debuggerem? –

+0

Skompiluj program do debugowania i uruchom program w debugerze. Debugger powie dokładnie, co się stało. – wallyk

+0

Debugger gdb nie podaje mi żadnych szczegółów - po prostu twierdzi, że znaleziono błąd segfault. – higz555

Odpowiedz

3

Zamiast tego:

char *para; 
fgets(para, 1000, stdin); 

napisać to:

char para[1000]; 
fgets(para, 1000, stdin); 

W pierwszym wariancie para to wskaźnik, który wskazuje gdzieś w pamięci, a do tego gdzieś użytkownik -nowy ciąg jest napisany. Najprawdopodobniej, para wskazuje na nieprawidłowy adres, powodując natychmiastowe zawieszenie twojego programu.

+0

Naprawiono błąd segmentacji - dziękuję! Teraz moje wyrażenia regularne nie są poprawnie analizowane. Powrót do deski kreślarskiej. – higz555

2

Wezwałaś regfree wewnątrz pętli. Drugi raz wokół pętli wywołujesz regexec w pamięci zwalnianej z niezdefiniowanym zachowaniem.

0

Niepoprawnie używasz strtok_r().

Aby przeanalizować ciąg znaków za pomocą strtok_r(), w pierwszym wywołaniu pierwszym argumentem jest wskaźnik do łańcucha, który chcesz przeanalizować. Kolejne wywołania funkcji strtok_r() w celu przeanalizowania tego samego ciągu powinny mieć wartość NULL przekazaną jako pierwszy argument. Co robisz:

ptr = ptr1; 
sentence = strtok_r(ptr, delim, &ptr1); 

nie ma sensu.

+0

Rozumiem, że wskaźnik wewnątrz strtok_r wskazywał na podzielony ciąg znaków po znalezieniu separatora i mógł rekursywnie przeciąć ciąg znaków. Mi to pasuje. – higz555

+1

Ma sens dla mnie. Tak często używam strtok_r. – Joshua