CallStack获取函数堆栈

之前总看Android的源码感觉CallStack做的很不错,现在终于用户三方库libunwind做出了自己的CallStack,虽然代码不多,但也是自己写的

上代码
/*************************************************************************
    > File Name: callstack.h
    > Author: hsz
    > Mail:
    > Created Time: Tue 27 Jul 2021 06:02:23 PM CST
 ************************************************************************/

#ifndef __ALIAS_CALLSTACK_H__
#define __ALIAS_CALLSTACK_H__
#include <log/log.h>			// 自己写的log
#include <stdio.h>
#include <vector>
#include <utils/string8.h>		// 仿照Android String8,添加了移动构造和移动赋值

namespace Alias {

class CallStack {
public:
    CallStack();
    CallStack(const char* logtag, int32_t ignoreDepth = 1);
    ~CallStack();

    void clear() { mStackFrame.clear(); }

    // Immediately collect the stack traces for the specified thread.
    // The default is to dump the stack of the current call.
    void update(int32_t ignoreDepth = 2);

    void log(const char* logtag,
             LogLeval::Leval leval = LogLeval::DEBUG) const;

    // Return a string (possibly very long) containing the complete stack trace.
    String8 toString() const;

    // Get the count of stack frames that are in this call stack.
    size_t size() const { return mStackFrame.size(); }

private:
    std::vector<String8>    mStackFrame;
    uint32_t                mSkip;
};
} // namespace Alias

#endif // __ALIAS_CALLSTACK_H__
/*************************************************************************
    > File Name: callstack.cpp
    > Author: hsz
    > Mail:
    > Created Time: Tue 27 Jul 2021 06:02:27 PM CST
 ************************************************************************/

#define UNW_LOCAL_ONLY
#include "callstack.h"
#include <cxxabi.h>
#include <libunwind.h>
#include <stdlib.h>

namespace Alias {
CallStack::CallStack()
{

}

CallStack::CallStack(const char* logtag, int32_t ignoreDepth)
{
    this->update(ignoreDepth + 1);
    this->log(logtag);
}

CallStack::~CallStack()
{
    
}

void CallStack::update(int32_t ignoreDepth)
{
    mSkip = ignoreDepth;
    unw_cursor_t cursor;
    unw_context_t context;

    unw_getcontext(&context);
    unw_init_local(&cursor, &context);

    while (unw_step(&cursor) > 0)
    {
        unw_word_t offset, funcPointer;
        unw_get_reg(&cursor, UNW_REG_IP, &funcPointer);
        if (funcPointer == 0) {
            break;
        }

        char sym[256];
        if (unw_get_proc_name(&cursor, sym, sizeof(sym), &offset) == 0) {
            char *nameptr = sym;
            int status = -1;
            char *demangled = abi::__cxa_demangle(sym, nullptr, nullptr, &status);
            if (status == 0) {
                nameptr = demangled;
            }
            mStackFrame.push_back(std::move(String8::format("-0x%012x: (%s + %p)", funcPointer, nameptr, offset)));
            std::free(demangled);
        } else {
            mStackFrame.push_back(std::move(String8::format("(unable to obtain symbol name for this frame)")));
        }
    }
}

void CallStack::log(const char* logtag, LogLeval::Leval leval) const
{
    for (size_t i = 0; i < mStackFrame.size() - mSkip; ++i) {
        log_write(leval, logtag, "%s\n", mStackFrame[i].c_str());
    }
}

String8 CallStack::toString() const
{
    String8 str;
    for (size_t i = 0; i < mStackFrame.size(); ++i) {
        str += mStackFrame[i];
        str += "\n";
    }
    return std::move(str);
}

} // namespace Alias
·测试代码
#include <utils/callstack.h>
#include <utils/thread.h>

namespace ns
{
    template <typename T, typename U>
    void func(T t, U u)
    {
        Alias::CallStack cs;
        cs.update();
        Alias::String8 str = cs.toString();
        printf("%s\n\n\n", str.c_str());

        cs.log("DEBUG");
    }
}

template <typename T>
struct Len
{
public:
    void len()
    {
        Alias::String8 s;
        ns::func(t, s);
    }
private:
    T t;
};

int thread(void *arg)
{
    Len<int> l;
    l.len();
    return 0;
}

int main()
{
    Len<int> l;
    l.len();

    Alias::Thread th("Thread", thread);
    th.run();
    sleep(2);
    return 0;
}
编译

在这里插入图片描述

在这里插入图片描述

运行

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值