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
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。