我试图找到一个随机错误(我没有特定的senario),这会导致我的C ++ linux程序崩溃。 我知道如果我使用gdb并且应用程序崩溃,我可以使用" bt"命令并获取崩溃的调用堆栈。 我不能使用gdb(logisitic问题),崩溃是随机的。
由于
答案 0 :(得分:1)
您可以使用__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;
}
答案 1 :(得分:0)
还有另一种方法来获取崩溃程序的回溯,但是当然它不如gdb的回溯,这里描述了该解决方案:https://stackoverflow.com/a/24573266/4442731
简而言之,您需要使用以下选项编译程序:
-g -rdynamic
然后您需要注册信号处理程序(SIGSEGV可能是您需要的信号):
signal(SIGSEGV, callbackWhenSignalOccures);
在函数callbackWhenSignal中,您可以使用函数显示回溯: How to automatically generate a stacktrace when my program crashes
关于gdb -我不知道您所说的“我不能使用gdb(逻辑问题)”是什么意思,但是您不必以交互方式运行gdb,您只需显示从核心回溯,然后gdb将自动退出:
ulimit -c unlimited
./program # it crashes
gdb -silent ./program core --eval-command=backtrace --batch
关于死锁,我找到了解决方法:http://man7.org/linux/man-pages/man3/backtrace.3.html