我写了以下代码:
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有什么关系(写入* book内存可能?)但为什么呢? 我想逐段阅读一份文件(UTF-8),然后做一些本代码中没有的内容。
答案 0 :(得分:2)
您没有初始化bufferln
,因此当您将新行连接(wcsncat()
)到未初始化数据的末尾时,您不知道代码将在何处写入。
你还在输入缓冲区buffer
的末尾的空终止符上写了一个(宽)空格,所以你不知道什么会被复制到随机位置;复制将在下一次广泛的NUL上停止。
答案 1 :(得分:1)
可能发生的是你的wcsncat(),根据文档的说法:
” 描述 wcsncat()函数只将ws2指向的字符串的前n个字符追加到ws1指向的字符串的末尾。如果在n个字符之前在ws2中出现NULL字符,则所有直到NULL字符的字符都将附加到ws1。 ws2的第一个字符覆盖ws1的终止NULL字符。 NULL终止字符始终附加到结果,如果用于复制的对象重叠,则行为未定义。 “
因此它会通过覆盖第一次出现的NULL字符而继续追加到bufferln。因此,如果if(wcscmp(buffer,L“\ n”)== 0)返回FALSE,您将最终超出分配的FILE_READ_BUFFER缓冲区并将文件溢出到bufferln边界之外,最终可能最终破坏堆栈。
在大多数情况下,堆栈会向下扩展并且必须到达某些实际上为FAULT的区域,因为在大多数系统上不允许访问虚拟地址页面的前2页。这是一个没有实际意义的原因。但主要原因是,一旦读取数据,就必须尝试将数据写入,因为读写缓冲区的长度相同。
HTH
答案 2 :(得分:0)
如果该行为空(\ n被\ 0替换),则字符串长度为null,并且strlen()-1指向缓冲区。
编辑: 我弄错了;你只是追加太多了。增加缓冲区大小,读取较短的行或两者。 并避免使用strcat();