сигнал 11 (SIGSEGV) - PullRequest
       16

сигнал 11 (SIGSEGV)

2 голосов
/ 16 сентября 2011

Я написал следующий код:

FILE *book;
wchar_t bufferln[FILE_READ_BUFFER];
wchar_t buffer[FILE_READ_BUFFER];
book = fopen(file, "r");
if(book == NULL){
    perror("Es ist ein Fehler beim lesen des Buches aufgetreten");
    return EXIT_FAILURE;
}
while(fgetws(buffer, FILE_READ_BUFFER, book) != NULL){
    if(wcscmp(buffer, L"\n") == 0){
        bufferln[0] = L'\0';
        continue;
    }
    buffer[wcsnlen(buffer, FILE_READ_BUFFER)-1] = L' ';
    wcsncat(bufferln, buffer, FILE_READ_BUFFER);
}
return EXIT_SUCCESS;

Сбой при SIGSEGV.Я запустил valgrind, который показывает следующее:

==11251== Conditional jump or move depends on uninitialised value(s)
==11251==    at 0x40BD5CF: wcsncat (wcsncat.c:36)
==11251==    by 0x804865D: read_book (book.c:18)
==11251==    by 0x804872B: main (main.c:19)
==11251==  Uninitialised value was created by a stack allocation
==11251==    at 0x80485B7: read_book (book.c:3)
==11251== 
==11251== Invalid read of size 4
==11251==    at 0x40A58E2: fgetws (iofgetws.c:52)
==11251==    by 0x804867D: read_book (book.c:12)
==11251==    by 0x6D: ???
==11251==  Address 0x65 is not stack'd, malloc'd or (recently) free'd
==11251== 
==11251== 
==11251== Process terminating with default action of signal 11 (SIGSEGV)
==11251==  Access not within mapped region at address 0x65
==11251==    at 0x40A58E2: fgetws (iofgetws.c:52)
==11251==    by 0x804867D: read_book (book.c:12)
==11251==    by 0x6D: ???
==11251==  If you believe this happened as a result of a stack
==11251==  overflow in your program's main thread (unlikely but
==11251==  possible), you can try to increase the size of the
==11251==  main thread stack using the --main-stacksize= flag.
==11251==  The main thread stack size used in this run was 8388608.

Я думаю, что проблема как-то связана с моим использованием wcsncat (возможно, запись в * книжную память?), Но почему?Я хочу прочитать документ (UTF-8) абзац за абзацем, а затем делать вещи, которых пока нет в этом коде.

Ответы [ 3 ]

2 голосов
/ 16 сентября 2011

Вы не инициализируете bufferln, поэтому не знаете, куда будет записываться ваш код, когда вы объединяете (wcsncat()) новую строку в конце неинициализированных данных.

Вы также пишете (широкий) пробел над нулевым терминатором в конце входного буфера buffer, так что вы не представляете, что будет скопировано в случайное место;копирование остановится, когда оно в следующий раз попадет в широкий NUL.

1 голос
/ 17 сентября 2011

Может случиться так, что ваш wcsncat (), который согласно документации делает:

» ОПИСАНИЕ Функция wcsncat () добавляет не более первых n символов строки, на которую указывает ws2, к концу строки, на которую указывает ws1. Если символ NULL появляется в ws2 перед n символами, все символы вплоть до символа NULL добавляются к ws1. Первый символ ws2 перезаписывает завершающий нулевой символ ws1. Завершающий символ NULL всегда добавляется к результату, и если объекты, используемые для копирования, перекрываются, поведение не определено. «

Таким образом, он продолжает добавляться в bufferln, начиная с перезаписи первого появления символа NULL. Таким образом, в случаях, когда if (wcscmp (buffer, L "\ n") == 0) возвращает FALSE, вы в конечном итоге переполняете свой выделенный буфер FILE_READ_BUFFER, выливаете файл за пределы границы bufferln и, возможно, разрушаете стек.

В большинстве случаев стеки растут вниз, и, должно быть, они достигли некоторых регионов, которые на самом деле ОШИБКА, потому что доступ к первым 2 страницам ваших страниц виртуального адреса не разрешен в большинстве систем. Это спорный вопрос о том, почему там произошел сбой. Но главная причина в том, что вы должны попытаться записать данные куда-нибудь, как только прочитаете их, поскольку ваши буферы чтения и записи имеют одинаковую длину.

НТН

0 голосов
/ 16 сентября 2011

Если строка пустая (\ n заменяется на \ 0), длина строки равна нулю, а strlen () -1 указывает на точку ниже буфера.

EDIT: Я неправильно понял; Вы просто добавляете слишком много. Увеличьте размер буфера, читайте короткие строки или оба. И избегайте strcat ();

...