list相關死機

老方法,打開core文件查看堆棧
GNU gdb (Hisilicon_v300) 7.4.50.20120716-cvs
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=i386-redhat-linux --target=arm-hisiv300-linux-uclibcgnueabi".
For bug reporting instructions, please see:
<http://www.hisilicon.com/cn/service/claim.html>...
Reading symbols from /home05/18635/test/Challenge_Debug...done.
(gdb) core-file core-Challenge_Debug-1168-1483697572
(gdb) bt
#0  operator++ (this=<synthetic pointer>)
    at /opt/hisi-linux/x86-arm/arm-hisiv300-linux/arm-hisiv300-linux-uclibcgnueabi/include/c++/4.8.3/bits/stl_list.h:235
#1  __distance<std::_List_const_iterator<CEvents::EVENT_STATE> > (__last=..., __first=...)
    at /opt/hisi-linux/x86-arm/arm-hisiv300-linux/arm-hisiv300-linux-uclibcgnueabi/include/c++/4.8.3/bits/stl_iterator_base_funcs.h:82
#2  distance<std::_List_const_iterator<CEvents::EVENT_STATE> > (__last=..., __first=...)
    at /opt/hisi-linux/x86-arm/arm-hisiv300-linux/arm-hisiv300-linux-uclibcgnueabi/include/c++/4.8.3/bits/stl_iterator_base_funcs.h:118
#3  size (this=0x5f7b8a4) at /opt/hisi-linux/x86-arm/arm-hisiv300-linux/arm-hisiv300-linux-uclibcgnueabi/include/c++/4.8.3/bits/stl_list.h:874


(gdb) f 0
#0  operator++ (this=<synthetic pointer>)
    at /opt/hisi-linux/x86-arm/arm-hisiv300-linux/arm-hisiv300-linux-uclibcgnueabi/include/c++/4.8.3/bits/stl_list.h:235
235             _M_node = _M_node->_M_next;
(gdb) p _M_node
Dwarf Error: Cannot find DIE at 0x34e243f 
死機的根本原因是內存查看了一個不可訪問的地址。

由於在gdb下查看list容器不是很方便,從網上下載了一個腳本stl-views-1.0.3.gdb
 

在gdb下輸入如下的命令

(gdb) source stl-views-1.0.3.gdb
(gdb) plist m_queue

省略中間的打印結果,從打印結果看,list沒有爲空的節點

這個時候就推測有沒有可能是多線程問題引入。


打印寄存器地址

(gdb) info r
r0             0x0      0
r1             0x0      0
r2             0x0      0
r3             0x180    384
r4             0x5f7b878        100120696
r5             0x727fcc8        120061128
r6             0x5f7b8b0        100120752
r7             0x655a0a8        106274984
r8             0x655a168        106275176
r9             0x5f7b8b4        100120756
r10            0x5f7b8a4        100120740
r11            0x3d1c1014       1025249300
r12            0x0      0
sp             0x3d1c0e90       0x3d1c0e90
lr             0x76f006ac       1995441836
pc             0x2a603c 0x2a603c <CEvents::ThreadProc()+36>
cpsr           0x80000010       -2147483632

從arm平臺的寄存器作用我們可知,r0-r3是入參寄存器

查看反彙編指令

   0x002a6018 <+0>:     push    {r4, r5, r6, r7, r8, r9, r10, lr}
   0x002a601c <+4>:     mov     r4, r0
   0x002a6020 <+8>:     add     r9, r0, #60     ; 0x3c
   0x002a6024 <+12>:    add     r10, r0, #44    ; 0x2c
   0x002a6028 <+16>:    mov     r0, r9
   0x002a602c <+20>:    bl      0xb89910 <Dahua::Infra::CSemaphore::pend()>
   0x002a6030 <+24>:    ldr     r2, [r4, #44]   ; 0x2c
   0x002a6034 <+28>:    mov     r3, #0
   0x002a6038 <+32>:    cmp     r2, r10
=> 0x002a603c <+36>:    ldrne   r2, [r2]
   0x002a6040 <+40>:    addne   r3, r3, #1

 從C++的編譯知識可以知道,this指針是函數的第一個參數,而r0從r4賦值而來,到執行到死機那一步的

時候r0的值變爲0。而一般多線程死機的情況下,纔會出現寄存器和內存不一致的情況。


再看看代碼中還有哪裏改變了m_queue的值。

 bool recvMessage 
 {
......

   m_queue.size();

.......

發現有人修改了以前一處未加鎖的m_queue訪問。基本確定是多線程問題。
將上面的斷言去掉後,就解決了多線程的問題

從上面要瞭解到兩點,
一:stl標準庫的容器都是非線程安全,使用時要注意數據安全
第二:儘量採用RAII的方法管理數據的串行訪問,避免有地方遺漏,造成線程不安全

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章