我試圖找到一個隨機錯誤(我沒有特定的senario),它會導致我的C++ linux程序崩潰。 我知道如果我使用gdb和應用程序崩潰,我可以使用「bt」命令並獲取崩潰的調用堆棧。 我不能使用gdb(logisitic問題),崩潰是隨機的。如何獲得崩潰函數的回溯(調用堆棧)或沒有gdb的死鎖?
- 有沒有辦法在Linux中獲取崩潰的C++應用程序的調用堆棧,而不使用gdb?
- 有沒有辦法知道是否有死鎖(有和沒有gdb)?
感謝
我試圖找到一個隨機錯誤(我沒有特定的senario),它會導致我的C++ linux程序崩潰。 我知道如果我使用gdb和應用程序崩潰,我可以使用「bt」命令並獲取崩潰的調用堆棧。 我不能使用gdb(logisitic問題),崩潰是隨機的。如何獲得崩潰函數的回溯(調用堆棧)或沒有gdb的死鎖?
感謝
你可以使用__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;
}
謝謝,有沒有辦法讓它沒有編碼? (從linux文件?) – user3668129 2015-04-02 03:46:56
U可以通過gdb打開coredump文件。爲什麼你不喜歡gdb?它如此強大... – 2015-04-02 04:01:33
我喜歡它,但不能在工作空間運行它我有 – user3668129 2015-04-03 04:12:45
你可以將代碼添加到您的程序?您可以捕獲違規信號或異常,並在GNU C庫中調用[backtrace](http://www.gnu.org/software/libc/manual/html_node/Backtraces.html)函數之一。 – 2015-04-01 18:39:15
你能夠得到一個核心文件並運行gdb,或者gdb根本不可用? – 2015-04-01 18:41:18