Qt编程中segfault问题解决方法

本文介绍在Linux环境下,Qt编程中segfault问题解决方法。

1.问题原因

segfault问题是编程中较为常见的错误,造成此问题的原因通常是程序访问了不允许访问的存储区域,比如C++程序中数组访问越界,通常会导致segfalut问题。出现segfault问题通常会导致程序崩溃,无法运行。

2.确认问题

前面介绍过,出现segfault问题通常会导致程序崩溃,但是导致程序崩溃的也有可能是其他原因,这时就需要确认是segfault问题。程序出现崩溃后,在Linux环境下,可以输入:

sudo dmesg

这里以1个项目问题为例,dmesg后出现:

show_signal_msg: 46 callbacks suppressed
[ 1155.768459] QThread[4022]: segfault at 7f3a2c021000 ip 0000564cd13fca33 sp 00007f3a32a2a6f0 error 4 in LightSource[564cd13f6000+18000]
[ 1155.768463] Code: 55 dc c7 45 fc 00 00 00 00 c6 45 fa 00 c6 45 fb 00 c7 45 fc 00 00 00 00 8b 45 fc 3b 45 dc 73 45 8b 55 fc 48 8b 45 e0 48 01 d0 <0f> b6 00 30 45 fa c6 45 fb 08 80 7d fb 00 74 25 0f b6 45 fa 84 c0

从打印消息可以很明显看出是segfault问题。

3.问题排查

1)确认故障位置

确认故障位置很关键,它有助于我们进一步找到在那个函数中出现segfault问题。

从打印消息中我们知道程序是从BASE:564cd13f6000处开始执行的,出现segfault问题后的IP(也就是程序计数器指针)为:0000564cd13fca33,那么程序相对于基地址的位置为:

Address=IP-BASE

带入值,可得:

Address=0000564cd13fca33-564cd13f6000=6a33

也就是说,程序在运行到相对0起始地址的6a33位置处出错。

2)确认函数位置

知道了报错地址,就需要进一步确认在那个函数中出现此问题。

这里有2种方法:

a)方法1

在Debug目录下,输入:

addr2line -e LightSource 6a33

命令的功能是实现有地址到程序行的转换。注意,这里要使用Debug版本的程序。

输出:

/home/xxx/Projects/LightSource/build-LightSource-Desktop_Qt_5_13_2_GCC_64bit-Debug/../LightSource/comm.cpp:366

由输出我们知道报错的位置在comm.cpp的366行。进入comm.cpp定位到366行就知道在哪里导致segfault问题了。

b)方法2

方法2是采用反汇编的方式,在Debug目录下,输入:

sudo objdump -ld LightSource > ~/Desktop/dump.txt

将反汇编后的结果导出到dump.txt中,然后,打开dump.txt,搜索6a33地址,如下所示:

00000000000069fc <_ZN4Comm8calcCRC8EPKhj>:
    69fc:	55                   	push   %rbp
    69fd:	48 89 e5             	mov    %rsp,%rbp
    6a00:	48 89 7d e8          	mov    %rdi,-0x18(%rbp)
    6a04:	48 89 75 e0          	mov    %rsi,-0x20(%rbp)
    6a08:	89 55 dc             	mov    %edx,-0x24(%rbp)
    6a0b:	c7 45 fc 00 00 00 00 	movl   $0x0,-0x4(%rbp)
    6a12:	c6 45 fa 00          	movb   $0x0,-0x6(%rbp)
    6a16:	c6 45 fb 00          	movb   $0x0,-0x5(%rbp)
    6a1a:	c7 45 fc 00 00 00 00 	movl   $0x0,-0x4(%rbp)
    6a21:	8b 45 fc             	mov    -0x4(%rbp),%eax
    6a24:	3b 45 dc             	cmp    -0x24(%rbp),%eax
    6a27:	73 45                	jae    6a6e <_ZN4Comm8calcCRC8EPKhj+0x72>
    6a29:	8b 55 fc             	mov    -0x4(%rbp),%edx
    6a2c:	48 8b 45 e0          	mov    -0x20(%rbp),%rax
    6a30:	48 01 d0             	add    %rdx,%rax
    6a33:	0f b6 00             	movzbl (%rax),%eax
    6a36:	30 45 fa             	xor    %al,-0x6(%rbp)
    6a39:	c6 45 fb 08          	movb   $0x8,-0x5(%rbp)
    6a3d:	80 7d fb 00          	cmpb   $0x0,-0x5(%rbp)
    6a41:	74 25                	je     6a68 <_ZN4Comm8calcCRC8EPKhj+0x6c>
    6a43:	0f b6 45 fa          	movzbl -0x6(%rbp),%eax
    6a47:	84 c0                	test   %al,%al
    6a49:	79 0e                	jns    6a59 <_ZN4Comm8calcCRC8EPKhj+0x5d>
    6a4b:	0f b6 45 fa          	movzbl -0x6(%rbp),%eax
    6a4f:	01 c0                	add    %eax,%eax
    6a51:	83 f0 31             	xor    $0x31,%eax
    6a54:	88 45 fa             	mov    %al,-0x6(%rbp)
    6a57:	eb 03                	jmp    6a5c <_ZN4Comm8calcCRC8EPKhj+0x60>
    6a59:	d0 65 fa             	shlb   -0x6(%rbp)
    6a5c:	0f b6 45 fb          	movzbl -0x5(%rbp),%eax
    6a60:	83 e8 01             	sub    $0x1,%eax
    6a63:	88 45 fb             	mov    %al,-0x5(%rbp)
    6a66:	eb d5                	jmp    6a3d <_ZN4Comm8calcCRC8EPKhj+0x41>
    6a68:	83 45 fc 01          	addl   $0x1,-0x4(%rbp)
    6a6c:	eb b3                	jmp    6a21 <_ZN4Comm8calcCRC8EPKhj+0x25>
    6a6e:	0f b6 45 fa          	movzbl -0x6(%rbp),%eax
    6a72:	5d                   	pop    %rbp
    6a73:	c3                   	retq 

我们就可以知道程序出现问题的地方在"_ZN4Comm8calcCRC8EPKhj",进而很容易的就知道是Comm中的calcCRC8函数了。其实,我们也可以发现在”2.确认问题”中的Code内容也在这里可以发现。

如果是库函数中的某个地址,也可以使用这种方法,不过就要先进入库所在目录了。

3)故障解决

故障解决的方法就不详细介绍了。

4.其他方法

1)集成开发环境(IDE)方法

如果故障容易再现或有一定的触发手段情况下,在使用开发环境下进入Debug,触发故障,这时Debugger会Hold住,我们根据backtrace就可以知道出现问题时的栈帧,即函数调用关系,以及一些辅助的信息,比如出现问题时相应的一些变量值,有助于我们找到问题原因。注意:在.pro中添加:

QMAKE_CXXFLAGS += -g

2)gdb方法

这个和1)比较类似,1)中的Debugger也不过是封装了gdb而已(Linux环境下),命令行下输入:

gdb LightSource
run

触发故障后,输入

backtrace
backtrace full

总结,本文介绍了Qt编程中segfault问题解决方法。

你可能感兴趣的:(Qt编程,qt,开发语言)