2015-04-01 56 views
0

我試圖找到一個隨機錯誤(我沒有特定的senario),它會導致我的C++ linux程序崩潰。 我知道如果我使用gdb和應用程序崩潰,我可以使用「bt」命令並獲取崩潰的調用堆棧。 我不能使用gdb(logisitic問題),崩潰是隨機的。如何獲得崩潰函數的回溯(調用堆棧)或沒有gdb的死鎖?

  1. 有沒有辦法在Linux中獲取崩潰的C++應用程序的調用堆棧,而不使用gdb?
  2. 有沒有辦法知道是否有死鎖(有和沒有gdb)?

感謝

+1

你可以將代碼添加到您的程序?您可以捕獲違規信號或異常,並在GNU C庫中調用[backtrace](http://www.gnu.org/software/libc/manual/html_node/Backtraces.html)函數之一。 – 2015-04-01 18:39:15

+1

你能夠得到一個核心文件並運行gdb,或者gdb根本不可用? – 2015-04-01 18:41:18

回答

0

你可以使用__cxa_demangle()獲取堆棧信息,像這樣:

string OException::strGetSourceCode(const string& p_strFileName,const string& p_strAddressInfo) throw() 
{ 
    char l_acBuf[CBUFFLEN] = {0}; 
    char l_acAddress[CBUFFLEN] = {0}; 
    memcpy(l_acBuf, p_strAddressInfo.c_str(), p_strAddressInfo.length()); 
    if(sscanf(l_acBuf,"%*[^[][0x%[^]]", l_acAddress)==1) 
    { 
     FILE *l_pFp; 
     stringstream l_ss; 
     if(p_strFileName.find(".so")!=string::npos) 
     { 
      unsigned int l_lOffset=strtol(l_acAddress,NULL,16)-strtol(strGetBaseAddress(p_strFileName).c_str(),NULL,16); 
      snprintf(l_acAddress,sizeof(l_acAddress),"%x",l_lOffset); 
     } 

     l_ss << "addr2line 0x" << l_acAddress<< " -i -e " << p_strFileName; 
     if((l_pFp = popen(l_ss.str().c_str(), "r"))) { 
      if(fgets(l_acAddress, CBUFFLEN, l_pFp) != NULL) { 
       l_acAddress[strlen(l_acAddress) - 1] = '\0'; 
      } 
     } 
     return l_acAddress; 
    } 
    return l_acBuf; 
} 
string OException::strGetBaseAddress(const string& p_soFileName) throw() 
{ 
    int l_iPid=getpid(); 
    char l_acFileName[CBUFFLEN]={0}; 
    char l_acCmd[CBUFFLEN]={0}; 
#ifdef __linux__ 
    snprintf(l_acFileName,sizeof(l_acFileName),"/proc/%d/maps",l_iPid); 
    snprintf(l_acCmd,sizeof(l_acCmd),"grep %s %s | head -1 | awk -F- \'{print $1}\'",p_soFileName.c_str(),l_acFileName); 
#endif 
    FILE* l_pFile=popen(l_acCmd,"r"); 
    char l_acBaseAddress[CBUFFLEN]={0}; 
    if(fgets(l_acBaseAddress,CBUFFLEN,l_pFile)!=NULL) 
     return l_acBaseAddress; 
    return ""; 
} 
void OException::vSaveStackTrace() throw() 
{ 
    void* l_acBuffer[CBUFFLEN]; 
    int l_iStackCount = ::backtrace(l_acBuffer, CBUFFLEN); //get the trace list //cout<<"l_iStackCount="<<l_iStackCount<<endl; 
    //translate trace message 
    char** l_pacStackResult = ::backtrace_symbols(l_acBuffer, l_iStackCount); 
    if (l_pacStackResult) 
    { 
     string l_strFormat=""; 
     string l_binFile=""; 
     m_sStack="==============BackTrace===========\n"; 
     for (int i = 0;i<l_iStackCount-1; i++)// 
     { 

      l_binFile=l_pacStackResult[i];//get the exe filename 
      l_binFile=l_binFile.substr(0,l_binFile.find('(',0)); 
      m_sStack.append(l_strFormat+"["+l_binFile+"]:"+strDemangle(l_pacStackResult[i])+"-->"); 
      m_sStack.append(strGetSourceCode(l_binFile,l_pacStackResult[i])); 
      m_sStack.push_back('\n'); 
      l_strFormat+=" "; 
     } 
     free(l_pacStackResult); 
    } 

} 
string OException::strDemangle(const char* p_acSymbol) throw() 
{ 
    size_t size; 
    int status; 
    char l_acTmp[CBUFFLEN]={0}; 
    char* l_pDemangled; 
    //first, try to demangle a c++ name 
    if (1 == sscanf(p_acSymbol, "%*[^(](%256[^)+]", l_acTmp)) { 
     if (NULL != (l_pDemangled = abi::__cxa_demangle(l_acTmp, NULL, &size, &status))) { 
      string l_strResult(l_pDemangled); 
      free(l_pDemangled); 
      return l_strResult; 
     } 
    } 
    //if that didn't work, try to get a regular c p_acSymbol 
    if (1 == sscanf(p_acSymbol, "%256s", l_acTmp)) { 
     return l_acTmp; 
    } 
    return p_acSymbol; 
} 
+0

謝謝,有沒有辦法讓它沒有編碼? (從linux文件?) – user3668129 2015-04-02 03:46:56

+0

U可以通過gdb打開coredump文件。爲什麼你不喜歡gdb?它如此強大... – 2015-04-02 04:01:33

+0

我喜歡它,但不能在工作空間運行它我有 – user3668129 2015-04-03 04:12:45

相關問題