多线程程序
pure virtual method called
terminate called without an active exception
会出这行log,但不知道是哪个线程打出来的.
断点下在同一个点,有时候会断下来,没挂,
有时会挂.
显然,挂的最直接原因是"pure virtual method called"
多线程同时进行下的挂, 某个线程慢了, 还不会crash...
因为gdb看backtrace只看到了部分的堆栈, (这里存疑惑,为什么)
```
#0 0x75f43d84 in raise () from /lib/libc.so.6
#1 0x75f47884 in abort () from /lib/libc.so.6
#2 0x75e91df0 in __gnu_cxx::__verbose_terminate_handler() ()
from /usr/lib/libstdc++.so.6
#3 0x75e8fc50 in ?? () from /usr/lib/libstdc++.so.6
```
这时候,要先切换到frame #3 ,
然后再往上分析堆栈(sp),看看有没有一些敏感的函数地址, 因为一些函数调用中, 会把执行那个函数时的LR寄存器存到堆栈里..
```
(gdb) info registers
r0 0x0 0
r1 0x397 919
r2 0x6 6
r3 0x651ff910 1696594192
r4 0x651fe854 1696589908
r5 0x76919ef4 1989254900
r6 0x69ff06a0 1778321056
r7 0x152 338
r8 0x1 1
r9 0x0 0
r10 0x38 56
r11 0x651fe88c 1696589964
r12 0x0 0
sp 0x651fe7f8 0x651fe7f8
lr 0x75e8fc50 1978203216
pc 0x75e8fc50 0x75e8fc50
cpsr 0x20080010 537395216
(gdb) x /60 $sp
0x651fe7f8: 0x75f11230 0x75e8fcc4 0x00000000 0x75e9096c
0x651fe808: 0x00000000 0x768b706c 0x0000005b 0x00000000
0x651fe818: 0x76a31558 0x76ac7c10 0x76a31558 0x76976074
0x651fe828: 0x651fe844 0x75300010 0x00000038 0x73b591d8
0x651fe838: 0x00000152 0x651fef90 0x00000000 0x6721a984
0x651fe848: 0x651fe8f4 0x75302db0 0x00000000 0x00000000
0x651fe858: 0x00000000 0x00000000 0x00000000 0x00000000
0x651fe868: 0x76aab240 0x00000202 0x00000000 0x00000001
0x651fe878: 0x76ac7c10 0x76a31558 0x69ff06a0 0x00000152
0x651fe888: 0x651fe8c4 0x76a31520 0x651fe8a4 0x651fe8f4
0x651fe898: 0x75302db0 0x69ff0468 0x651fe8c4 0x00000000
0x651fe8a8: 0x00000000 0x00000000 0x76ab1364 0x753028f8
0x651fe8b8: 0x00000001 0x76ac7c10 0x651fe92c 0x76a69d90
0x651fe8c8: 0x00000000 0x73b591d8 0x00000000 0x651fef90
0x651fe8d8: 0x00000000 0x00000038 0x651fe8f4 0x75313868
```
0x768b706c 这个地址是产品库的代码地址, 所以进到c++库中前,是在这相关的代码执行的.
这里其实是靠猜测...
```
(gdb) disass 0x768b706c
Dump of assembler code for function foo(char const*, string*, void*):
0x768b7024 <+0>: ldr r3, [r2, #4]
0x768b7028 <+4>: mov r12, #0
0x768b702c <+8>: push {r4, r5, lr}
0x768b7030 <+12>: sub sp, sp, #12
0x768b7034 <+16>: str r12, [sp, #4]
0x768b7038 <+20>: mov r4, r1
0x768b703c <+24>: ldr r12, [r3, #60] ; 0x3c
0x768b7040 <+28>: ldr r5, [pc, #72] ; 0x768b7090 <foo(char const*, string*, void*)+108>
0x768b7044 <+32>: cmp r12, #0
0x768b7048 <+36>: add r5, pc, r5
0x768b704c <+40>: beq 0x768b7088 <foo(char const*, string*, void*)+100>
0x768b7050 <+44>: ldr lr, [r12]
0x768b7054 <+48>: mov r1, r0
0x768b7058 <+52>: ldr r3, [r2]
0x768b705c <+56>: mov r0, r12
0x768b7060 <+60>: add r2, sp, #4
0x768b7064 <+64>: ldr r12, [lr, #64] ; 0x40
0x768b7068 <+68>: blx r12
0x768b706c <+72>: ldr r12, [sp, #4]
0x768b7070 <+76>: ldr r3, [pc, #28] ; 0x768b7094 <foo(char const*, string*, void*)+112>
0x768b7074 <+80>: ldr r3, [r5, r3]
0x768b7078 <+84>: str r12, [r4]
0x768b707c <+88>: str r3, [r4, #4]
0x768b7080 <+92>: add sp, sp, #12
0x768b7084 <+96>: pop {r4, r5, pc}
0x768b7088 <+100>: mvn r0, #0
0x768b708c <+104>: b 0x768b7070 <DEWrapper::OnXArcCommandRequest(char const*, ADLNA_String*, void*)+76>
0x768b7090 <+108>: andeq r2, r6, r4, lsr #29
0x768b7094 <+112>: andeq r0, r0, r0, lsl #27
End of assembler dump.
```
这段代码里调用了一个对象的虚函数,本应正常的.
分析此时这个对象的内存, 发现它的vptr中相应的函数是`__cxa_pure_virtual`,正常情况是直接对应着实际函数地址的.
The __cxa_pure_virtual
function is an error handler that is invoked when a pure virtual function is called.
应该是多线程环境下, 在另外的函数里析构了,(析构会怎么去修改对象?).