C/C++函数调用栈信息输出(backtrace & backtrace_symbols)
2023-12-14 17:37:05
C/C++函数调用栈信息输出(backtrace & backtrace_symbols)
最近工作,搞了一个死锁问题,加了好多输出无法定位问题。
就想着在锁操作调用的地方输出函数调用栈信息,试了一下,竟然实现了。
源代码
#include <iostream>
#include <mutex>
#include <execinfo.h>
#ifndef __STL_LOCKER_H__
#define __STL_LOCKER_H__
namespace STL
{
class STL_Locker
{
public:
static std::string printStackTrace()
{
std::string ret = "";
void *callstack[128];
int frames = backtrace(callstack, sizeof(callstack) / sizeof(callstack[0]));
char **strs = backtrace_symbols(callstack, frames);
if (strs == NULL)
{
return ret;
}
// 从1开始,是不输出最后一层printStackTrace函数的调用信息
for (int i = 1; i < frames; ++i)
{
ret.append(std::string(strs[i]));
ret.append("\n");
}
free(strs);
return ret;
}
public:
STL_Locker()
{
std::cout << "LYLOG StackTrace:\n"
<< printStackTrace();
std::cout << "LYLOG[" << __FILE__ << ":" << __LINE__ << "] " << __FUNCTION__ << "() INIT LOCK " << std::hex << &_mutex;
}
~STL_Locker()
{
std::cout << "LYLOG StackTrace:\n"
<< printStackTrace();
std::cout << "LYLOG[" << __FILE__ << ":" << __LINE__ << "] " << __FUNCTION__ << "() DESTROY LOCK " << std::hex << &_mutex;
}
void lock()
{
std::cout << "LYLOG StackTrace:\n"
<< printStackTrace();
std::cout << "LYLOG[" << __FILE__ << ":" << __LINE__ << "] " << __FUNCTION__ << "() START WRLOCK " << std::hex << &_mutex;
_mutex.lock();
std::cout << "LYLOG[" << __FILE__ << ":" << __LINE__ << "] " << __FUNCTION__ << "() ENDED WRLOCK " << std::hex << &_mutex;
}
void unlock()
{
std::cout << "LYLOG StackTrace:\n"
<< printStackTrace();
std::cout << "LYLOG[" << __FILE__ << ":" << __LINE__ << "] " << __FUNCTION__ << "() START UNLOCK " << std::hex << &_mutex;
_mutex.unlock();
std::cout << "LYLOG[" << __FILE__ << ":" << __LINE__ << "] " << __FUNCTION__ << "() ENDED UNLOCK " << std::hex << &_mutex;
}
private:
std::mutex _mutex;
};
}
#endif //__STL_LOCKER_H__
编译配置
如果不加次编译flags,只能输出函数地址,无法看到函数名称
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -rdynamic")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -rdynamic")
最终效果
StackTrace:
bin/ConfigService(_ZN3tbb6Locker6unlockEv+0x68) [0x556f47bb84]
bin/ConfigService(_ZN3tbb19concurrent_hash_mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt10shared_ptrI16VgAccessDetecterESt4hashIS6_ESt8equal_toIS6_ESaISt4pairIKS6_S9_EEE8AccessorINSt8__detail20_Node_const_iteratorISG_Lb0ELb1EEEED1Ev+0x28) [0x556f4c652c]
bin/ConfigService(_ZN8VgAccess9heartbeatERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES7_PKN2vg6access16HeartbeatRequestEPNS9_17HeartbeatResponseE+0x57c) [0x556f4c2b34]
bin/ConfigService(_ZN8VgAccess9HeartbeatEPN6google8protobuf13RpcControllerEPKN2vg6access16HeartbeatRequestEPNS5_17HeartbeatResponseEPNS1_7ClosureE+0x134) [0x556f4beac8]
/ConfigService/libs/libvg_pb.so(_ZN2vg6access19AccessNotifyService10CallMethodEPKN6google8protobuf16MethodDescriptorEPNS3_13RpcControllerEPKNS3_7MessageEPS9_PNS3_7ClosureE+0x104) [0x7f8fdeb028]
/ConfigService/libs/libbrpc.so(_ZN4brpc6policy17ProcessRpcRequestEPNS_16InputMessageBaseE+0xad0) [0x7f8ecdd724]
/ConfigService/libs/libbrpc.so(_ZN4brpc19ProcessInputMessageEPv+0x10) [0x7f8eccb7d0]
/ConfigService/libs/libbrpc.so(_ZN4brpc14InputMessenger13OnNewMessagesEPNS_6SocketE+0x4c0) [0x7f8eccc520]
/ConfigService/libs/libbrpc.so(_ZN4brpc6Socket12ProcessEventEPv+0x18) [0x7f8ed80c88]
/ConfigService/libs/libbrpc.so(_ZN7bthread9TaskGroup11task_runnerEl+0x94) [0x7f8ec24e08]
/ConfigService/libs/libbrpc.so(bthread_make_fcontext+0x18) [0x7f8ec0f350]
LYLOG[/home/work/ConfigService/src/common/concurrent_hash_map.h:60] unlock() START UNLOCK 0x55a9e9baa0
LYLOG[/home/work/ConfigService/src/common/concurrent_hash_map.h:63] unlock() ENDED UNLOCK 0x55a9e9baa0
这里面的函数名称是Name Mangling后的结果,不懂Name Mangling的,自行百度。
似乎有方法获取到原始函数名称,但是定位问题这种级别的输出已经足够了,没有再继续研究。
注意
次代码为了定位问题,定为完问题就删掉了。产品环境下慎用。
文章来源:https://blog.csdn.net/yjkhtddx/article/details/134998746
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!