多线程 list没有锁好导致的 不安全宕机问题


 


问题:因为代码中执行m_LoggerList.size()语句没有加锁,导致内存中出现了空指针,以下为状态推送线程的堆栈信息:

(gdb) thread 20
[Switching to thread 20 (Thread 4884)]#0  std::_List_const_iterator<_st_LOGGER*>::operator++() (this=0x20c6b498)
    at /opt/freeware/lib/gcc/powerpc-ibm-aix5.3.0.0/4.2.0/include/c++/bits/stl_list.h:224
224             _M_node = _M_node->_M_next;
(gdb) bt
#0  std::_List_const_iterator<_st_LOGGER*>::operator++() (this=0x20c6b498)
    at /opt/freeware/lib/gcc/powerpc-ibm-aix5.3.0.0/4.2.0/include/c++/bits/stl_list.h:224
#1  0x10014d2c in std::iterator_traits >::difference_type std::__distance >(std::_List_const_iterator<_st_LOGGER*>, std::_List_const_iterator<_st_LOGGER*>, std::input_iterator_tag) (__first=
      {_M_node = 0x0}, __last={_M_node = 0x20031b70})
    at /opt/freeware/lib/gcc/powerpc-ibm-aix5.3.0.0/4.2.0/include/c++/bits/stl_iterator_base_funcs.h:84
#2  0x10014e60 in std::iterator_traits >::difference_type std::distance >(std::_List_const_iterator<_st_LOGGER*>, std::_List_const_iterator<_st_LOGGER*>) (__first={_M_node = 0x20e51b08},
    __last={_M_node = 0x20031b70})
    at /opt/freeware/lib/gcc/powerpc-ibm-aix5.3.0.0/4.2.0/include/c++/bits/stl_iterator_base_funcs.h:119
#3  0x10014f50 in std::list<_st_LOGGER*, std::allocator<_st_LOGGER*> >::size() const (this=0x20031b70)
    at /opt/freeware/lib/gcc/powerpc-ibm-aix5.3.0.0/4.2.0/include/c++/bits/stl_list.h:660
#4  0x100172e4 in nsLogApi::CLogger::wlog2(PRIORITY_TYPE, char const*, char const*, char const*, char const*, char const*) (
    this=0x2002f518, enumLevel=PRIORITY_DEBUG, sSysID=0x200011f8 "Ag\ent", sLocation=0x20001378 "./Stat\eCh\eckThr\ead.cpp 201",
    sErrCode=0x20001578 "0", sDigest=0x10045044 "cli\ent线程池繁忙", sLogMsg=0x20019be4 "1234455")
    at ../public/p_logapi/src/logger.cpp:120
#5  0x1003ad4c in CStateCheckThread::Run() (this=0x200733f8) at ./StateCheckThread.cpp:201
#6  0x10035f70 in _ThreadEntry(void*) (pParam=0x200733f8) at ../public/p_frame/src/Thread.cpp:23
#7  0xd010d784 in _pthread_body () from /usr/lib/libpthreads.a(shr_xpg5.o)
(gdb) frame 0
#0  std::_List_const_iterator<_st_LOGGER*>::operator++() (this=0x20c6b498)
    at /opt/freeware/lib/gcc/powerpc-ibm-aix5.3.0.0/4.2.0/include/c++/bits/stl_list.h:224
224             _M_node = _M_node->_M_next;
(gdb) info f
Stack level 0, frame at 0x20c6b3f0:
 pc = 0x10014c80 in std::_List_const_iterator<_st_LOGGER*>::operator++()
    (/opt/freeware/lib/gcc/powerpc-ibm-aix5.3.0.0/4.2.0/include/c++/bits/stl_list.h:224); saved pc 0x10014d2c
 called by frame at 0x20c6b420
 source language c++.
 Arglist at 0x20c6b3f0, args: this=0x20c6b498
 Locals at 0x20c6b3f0, Previous frame's sp in r1
 Saved registers:
  r31 at 0x20c6b41c
(gdb) up
#1  0x10014d2c in std::iterator_traits >::difference_type std::__distance >(std::_List_const_iterator<_st_LOGGER*>, std::_List_const_iterator<_st_LOGGER*>, std::input_iterator_tag) (__first=
      {_M_node = 0x0}, __last={_M_node = 0x20031b70})
    at /opt/freeware/lib/gcc/powerpc-ibm-aix5.3.0.0/4.2.0/include/c++/bits/stl_iterator_base_funcs.h:84
84                ++__first;
(gdb) info f
Stack level 1, frame at 0x20c6b420:
 pc = 0x10014d2c
    in std::iterator_traits >::difference_type std::__distance >(std::_List_const_iterator<_st_LOGGER*>, std::_List_const_iterator<_st_LOGGER*>, std::input_iterator_tag)
    (/opt/freeware/lib/gcc/powerpc-ibm-aix5.3.0.0/4.2.0/include/c++/bits/stl_iterator_base_funcs.h:84); saved pc 0x10014e60
 called by frame at 0x20c6b480, caller of frame at 0x20c6b3f0
 source language c++.
 Arglist at 0x20c6b420, args: __first={_M_node = 0x0}, __last={_M_node = 0x20031b70}
 Locals at 0x20c6b420, Previous frame's sp in r1
 Saved registers:
  r31 at 0x20c6b47c, lr at 0x20c6b488
(gdb) up
(gdb) up
(gdb) up
#4  0x100172e4 in nsLogApi::CLogger::wlog2(PRIORITY_TYPE, char const*, char const*, char const*, char const*, char const*) (
    this=0x2002f518, enumLevel=PRIORITY_DEBUG, sSysID=0x200011f8 "Ag\ent", sLocation=0x20001378 "./Stat\eCh\eckThr\ead.cpp 201",
    sErrCode=0x20001578 "0", sDigest=0x10045044 "cli\ent线程池繁忙", sLogMsg=0x20019be4 "1234455")
    at ../public/p_logapi/src/logger.cpp:120
120             if(m_LogConfig.m_iAsynLength > 0 && m_LoggerList.size() > m_LogConfig.m_iAsynLength)
(gdb) p m_LogConfig.m_iAsynLength
$1 = 8000
(gdb) p  m_LoggerList.size()
aix-thread: ptrace (57, 0) returned -1 (errno = 3 The process does not exist.)

由以上堆栈信息可以看出,在执行m_LoggerList.size()语句时出现了__first={_M_node = 0x0}的空地址, 导致程序在执行_M_node = _M_node->_M_next; 时出错。

解决

m_LogMutex.Lock();
if(m_LogConfig.m_iAsynLength > 0 && m_LoggerList.size() > m_LogConfig.m_iAsynLength){
printf("m_LoggerList Length:[%d]\n",m_LoggerList.size());
m_LogMutex.UnLock();
return;
}//在这里加上锁
m_LogMutex.UnLock();


 

 

你可能感兴趣的:(多线程,c++)