记一次难查的崩溃

多线程程序


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.


应该是多线程环境下, 在另外的函数里析构了,(析构会怎么去修改对象?).





  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值