C语言 信号 11 (SIGSEGV)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7447643/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
signal 11 (SIGSEGV)
提问by Jonas Osburg
I wrote the following code:
我写了以下代码:
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'==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.
';
continue;
}
buffer[wcsnlen(buffer, FILE_READ_BUFFER)-1] = L' ';
wcsncat(bufferln, buffer, FILE_READ_BUFFER);
}
return EXIT_SUCCESS;
It crashes with SIGSEGV. I ran valgrind which shows the following:
它与 SIGSEGV 一起崩溃。我运行 valgrind 显示以下内容:
##代码##I think the problem is somehow related to my usage of wcsncat (writing into *book memory maybe?) but why? I want to read a document (UTF-8) paragraph by paragraph and then do stuff that is not in this code yet.
我认为这个问题在某种程度上与我对 wcsncat 的使用有关(可能写入 *book 内存?)但为什么呢?我想逐段阅读文档(UTF-8),然后执行此代码中尚未包含的内容。
采纳答案by Anoop Menon
What could be happening is that your wcsncat() which as per documentation does :
可能发生的事情是您的 wcsncat() 根据文档所做的:
" DESCRIPTION The wcsncat() function appends no more than the first n characters of the string pointed to by ws2 to the end of the string pointed to by ws1. If a NULL character appears in ws2 before n characters, all characters up to the NULL character are appended to ws1. The first character of ws2 overwrites the terminating NULL character of ws1. A NULL terminating character is always appended to the result, and if the objects used for copying overlap, the behavior is undefined. "
" 描述 wcsncat() 函数将不超过 ws2 指向的字符串的前 n 个字符追加到 ws1 指向的字符串的末尾。如果 ws2 中的 n 个字符之前出现 NULL 字符,则直到 NULL 的所有字符字符附加到 ws1。ws2 的第一个字符覆盖 ws1 的终止 NULL 字符。NULL 终止字符总是附加到结果中,如果用于复制的对象重叠,则行为未定义。”
So it keeps appending to bufferln starting by overwriting the first occurence of NULL character. So in cases where if(wcscmp(buffer, L"\n") == 0) returns FALSE you will end up overrunning your allocated buffer of FILE_READ_BUFFER and spill the file outside the bufferln boundary and possibly end up corrupting the stack.
因此,它通过覆盖第一次出现的 NULL 字符开始附加到 bufferln。因此,在 if(wcscmp(buffer, L"\n") == 0) 返回 FALSE 的情况下,您最终将超出分配的 FILE_READ_BUFFER 缓冲区并将文件溢出到 bufferln 边界之外,并可能最终破坏堆栈。
In most cases stacks grow downwards and it must have reached some regions which actually FAULT because accessing the first 2 pages of your virtual address pages is not allowed on most systems. This is a moot point as to why it faulted there. But the main reason is that you have to try write the data somewhere once you have read it as your read and write buffers are of the same length.
在大多数情况下,堆栈会向下增长,并且它一定已经到达了一些实际上 FAULT 的区域,因为大多数系统不允许访问虚拟地址页面的前 2 页。关于它为什么在那里出错,这是一个有争议的问题。但主要原因是您必须尝试在读取数据后将其写入某处,因为读取和写入缓冲区的长度相同。
HTH
HTH
回答by Jonathan Leffler
You don't initialize bufferln, so you've no idea where your code is going to write when you concatenate (wcsncat()) the new line to the end of the uninitialized data.
您没有 initialize bufferln,因此当您将 ( wcsncat()) 新行连接到未初始化数据的末尾时,您不知道您的代码将写入何处。
You also write a (wide) space over the null terminator at the end of the input buffer buffer, so you've no idea what is going to be copied into the random location; copying will stop when it next hits a wide NUL.
您还在输入缓冲区末尾的空终止符上写了一个(宽)空格buffer,因此您不知道将要复制到随机位置的内容;复制将在下一次遇到宽 NUL 时停止。
回答by wildplasser
If the line is empty (\n gets replaced by \0) , the string length is null, and strlen() -1 points below the buffer.
如果该行为空 (\n 被 \0 替换),则字符串长度为空,并且 strlen() -1 指向缓冲区下方。
EDIT: I got it wrong; you are just appending too much. Increase your buffer size, read shorter lines, or both. And avoid strcat();
编辑:我弄错了;你只是追加太多。增加缓冲区大小,读取较短的行,或两者兼而有之。并避免 strcat();

