Search code examples
csplitsubstringc-stringswchar-t

wcstok causes segmentation fault


I'm writing program that splits cyrillic text from stdin and prints it line by line. After reading text using fgetws i am getting Segmentation fault. Debugging with gdb returns this:

Program received signal SIGSEGV, Segmentation fault.
wcstok (wcs=0x7fffffffda90 L"", delim=0x7fffffffda80 L" ,-", save_ptr=0x0) at wcstok.c:45
45      wcstok.c: No such file or directory.

Code:

#include <stdio.h>
#include <wchar.h>
#include <wctype.h>

int main() {
    wchar_t sentence[201];

    fgetws(sentence, 201, stdin);
    
    wchar_t delimiters[] = L" ,-";

    wchar_t *word = wcstok(sentence, delimiters, NULL);

    while (word != NULL) {
        wprintf(L"%ls", word);
        word = wcstok(NULL, delimiters, NULL);
    }

    return 0;
}

I am using gcc 9.4.0


Solution

  • These calls of wcstok

    wchar_t *word = wcstok(sentence, delimiters, NULL);
    
    while (word != NULL) {
        wprintf(L"%ls", word);
        word = wcstok(NULL, delimiters, NULL);
    }
    

    are incorrect. The third argument shall not be a null pointer.

    You should write something like the following

    wchar_t *ptr;
    
    wchar_t *word = wcstok(sentence, delimiters, &ptr);
    
    while (word != NULL) {
        wprintf(L"%ls", word);
        word = wcstok(NULL, delimiters, &ptr);
    }
    

    From the C Standard (7.29.4.5.7 The wcstok function):

    3 The first call in a sequence has a non-null first argument and stores an initial value in the object pointed to by ptr. Subsequent calls in the sequence have a null first argument and the object pointed to by ptr is required to have the value stored by the previous call in the sequence, which is then updated. The separator wide string pointed to by s2 may be different from call to call.