【发布时间】:2023-01-19 13:52:58
【问题描述】:
下面是当我在使用 gcc 构建时最初没有使用 fsanitize=address 时出现分段错误的堆栈跟踪。当我通过查看下面的跟踪详细信息来查看代码时,我没有在行号为convert_text (string=0x1a50276 "TESTER233", size=10) at caomenu.pc:12795的代码中发现任何错误
#0 0x00007ffff34bea9f in raise () from /lib64/libc.so.6
#1 0x00007ffff3491e05 in abort () from /lib64/libc.so.6
#2 0x00007ffff3501047 in __libc_message () from /lib64/libc.so.6
#3 0x00007ffff350819c in malloc_printerr () from /lib64/libc.so.6
#4 0x00007ffff350844c in munmap_chunk () from /lib64/libc.so.6
#5 0x00007ffff34f72e5 in fclose@@GLIBC_2.2.5 () from /lib64/libc.so.6
#6 0x000000000047337e in WriteTrace (cEntryText=0x488d73 "Running convert_text") at caomenu.pc:18426
#7 0x000000000045014a in convert_text (string=0x1a50276 "TESTER233", size=10) at caomenu.pc:12795
#8 0x0000000000450cca in load_user_data () at caomenu.pc:12922
#9 0x00000000004500c1 in display_user_security () at caomenu.pc:12772
#10 0x0000000000403862 in menu1 () at caomenu.pc:993
#11 0x00000000004017fa in main (ac=2, av=0x7fffffffe208) at caomenu.pc:562
下面是我用来跟踪发生的分段错误时的堆栈跟踪。这次使用了带有 gcc 的 -fsanitize=address 并构建了它。
gcc -fsanitize=address -g -o scrmenu caomenu.c superbox.c
这给了我堆栈跟踪,它表示确切的行号 (at caomenu.pc:13169),如下所示,代码中有错误。
(gdb) bt
#0 0x0000000000500cad in process_user_security () at caomenu.pc:13169
#1 0x00000000004fb291 in display_user_security () at caomenu.pc:12780
#2 0x000000000040732f in menu1 () at caomenu.pc:993
#3 0x0000000000402ed8 in main (ac=2, av=0x7fffffffe208) at caomenu.pc:562
(gdb)
在第 13169 行,以下是试图访问未初始化指针的语句,因为 commline 被声明为整数。但是之前没有初始化这个语句。
orCommodity[commline].commnum = 0;
在检查代码并用零 (int commline=0;) 初始化 commline 之后,代码被优雅地执行,没有任何分段错误。
所以,我得出一个结论,未初始化 commline 是整个问题的罪魁祸首。所以我再次在没有 fsanitize=address 的情况下运行代码,并预计这次它会给出任何分段错误。但令我惊讶的是,它再次抛出与上面第一个场景中所示相同的行 (caomenu.pc:12795)。所以我一直在敲我的头,如果不初始化 commline (int commline;) 是真正的罪魁祸首,它应该在代码中修复后顺利运行。但我在 stck 跟踪中得到了相同的行 12795,这不是越野车。如果有这方面的专家,可以对此有所了解。
【问题讨论】:
-
你有另一个错误。更多代码可能会有所帮助。
-
您的代码中很可能存在错误,例如写入已释放的内存、覆盖缓冲区或导致未定义行为的类似问题。这就是我们在没有看到您的任何代码的情况下可以说的全部内容。
-
任何不合格的编译器都应该警告您不要使用未初始化的变量。
-Wall -Wextra -pedantic-errors。少用头撞墙,多解决编译器已经发现并向您指出的错误 :) -
-fsanitize=address无法捕获所有错误。valgrind可以抓到更多。 (这是数学上不可能一个自动化的工具来捕捉全部错误:<en.wikipedia.org/wiki/Rice%27s_theorem>.) -
笔记:“程序测试可以用来显示错误的存在,但绝不能证明它们不存在!”