为什么这个程序会出现段错误?
我编写了一个名为 Mathtext 的程序。该程序通过将某些字符范围转换为 Unicode 范围(例如“数学字母符号”)来提供纯文本“样式”,以生成纯文本斜体、粗体、衬线等。
它作为逐行解释器工作,就像 shell ,在输入一行后输出翻译后的行,这意味着可以通过 cat/piped 输入文件来翻译整个文件,并且您可以通过以下方式“退出”“shell”。按 ^D,这是由标准输入命中 EOF 检测到的。
,当我按 ^D 并退出时,我仍然无法完全理解导致此问题的原因。
但是 /code> 有一点帮助;我现在知道问题是由按下 ^D 时转置中的 strlen 调用引起的,但是,永远不应该在 ^D 期间调用转置,因为 eof 是正确的!
Program received signal SIGSEGV, Segmentation fault. __strlen_sse2 () at ../sysdeps/x86_64/multiarch/../strlen.S:31 31 ../sysdeps/x86_64/multiarch/../strlen.S: No such file or directory. in ../sysdeps/x86_64/multiarch/../strlen.S (gdb) where #0 __strlen_sse2 () at ../sysdeps/x86_64/multiarch/../strlen.S:31 #1 0x0000000000400b0e in transpose (s=0x0, capsDelta=120263, smallDelta=120257, numDelta=0) at mathtext.c:58 #2 0x0000000000400e2b in main (argc=2, argv=0x7fffffffe4b8) at mathtext.c:92
I've written a program called Mathtext. This program gives plain text "style" by shifting certain character ranges into Unicode ranges such as 'mathematical letterlike symbols" to produce plain-text italics, bold, serif, etc.
It works as a line-by-line interpreter, like a shell, outputting the translated line after a line is entered. This means that files can be cat
/piped in to translate an entire file, as well as the fact that you can 'exit' the 'shell' by pressing ^D, which is detected by stdin hitting EOF.
Everything works. However, when I press ^D and exit, it segfaults. I still can't quite grasp what is causing this.
Compiling with -g -O0
helps a little; I now know that the problem arises from a strlen call in transpose when ^D is pressed. However, transpose should never be called during ^D, as eof is true!
Program received signal SIGSEGV, Segmentation fault. __strlen_sse2 () at ../sysdeps/x86_64/multiarch/../strlen.S:31 31 ../sysdeps/x86_64/multiarch/../strlen.S: No such file or directory. in ../sysdeps/x86_64/multiarch/../strlen.S (gdb) where #0 __strlen_sse2 () at ../sysdeps/x86_64/multiarch/../strlen.S:31 #1 0x0000000000400b0e in transpose (s=0x0, capsDelta=120263, smallDelta=120257, numDelta=0) at mathtext.c:58 #2 0x0000000000400e2b in main (argc=2, argv=0x7fffffffe4b8) at mathtext.c:92
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
大多数
feof()
的使用都是一个错误 - 这个程序在这个主循环中完美地演示了它:在文件末尾,
fgets()
将返回NULL
,然后下一次调用feof()
将返回 true。因此,正确的方法是测试输入函数的返回值 - 并且由于您无论如何都在进行该测试,因此无需调用feof()
(除非您想将文件错误与文件结尾)。Most uses of
feof()
are a bug - and this program demonstrates it perfectly in this main loop:At end-of-file,
fgets()
will returnNULL
, and then the next invocation offeof()
will return true. So the correct approach is to test the return value of your input function - and since you're doing that test anyway, there's no need to callfeof()
(unless you want to distinguish a file error from end-of-file).您的程序正在取消引用 NULL,因为
fgets
在错误或 EOF 时返回 NULL,并且您将其直接传递给转置,转置会天真地使用结果。Your program is dereferencing NULL, since
fgets
returns NULL on error or EOF, and you're passing this directly to transpose which uses the result naively.feof
无法预测未来。在您实际按下 ^D 键之前,它并不知道文件结束,此时您的程序将返回等待fgets
中的输入。读取文件不会产生错误,因为所有输入都已存在于开头。检查转置函数中是否有 NULL。feof
can't predict the future. It doesn't know it's the end of file until you actually press the ^D key, by which time your program is back waiting for input infgets
. Reading a file wouldn't produce the error because all the input is already present at the beginning. Check for NULL in your transpose function.