基于 C++20 的 std::source_location
和宏实现侵入式的函数调用栈追踪。
mtracer.hpp1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| #pragma once
#include <algorithm> #include <cstddef> #include <source_location> #include <stack> #include <string>
class MTracer { public: explicit MTracer(const std::source_location &location = std::source_location::current()) { get_stack().push(location); }
~MTracer() { get_stack().pop(); }
MTracer &operator=(const MTracer &) = delete; MTracer(const MTracer &) = delete;
[[nodiscard]] static std::string dump_string() { std::stack<std::source_location> tracer_stack(get_stack());
std::string str_result = "\nCall stack (MTRACER):";
std::size_t i = tracer_stack.size(); while (!tracer_stack.empty()) { std::string str_tmp = '\n' + std::to_string(i - 1) + ": " + format(tracer_stack.top()); std::ranges::replace(str_tmp, '\\', '/'); str_result += str_tmp; tracer_stack.pop(); --i; }
return str_result + '\n'; }
static std::string format(const std::source_location &location) { return std::string{location.file_name()} + ":" + std::to_string(location.line()) + " " + location.function_name(); }
private: static std::stack<std::source_location> &get_stack() { static std::stack<std::source_location> m_tracer_stack; return m_tracer_stack; } };
#ifdef USE_MTRACER
#define MTRACER_CB_INNER(a, b) a##b #define MTRACER_CB(a, b) MTRACER_CB_INNER(a, b)
#define MTRACER MTracer MTRACER_CB(tmp_tracer_, __LINE__) #define MTRACER_DUMP_STRING MTracer::dump_string() #define MTRACER_DUMP \ do { std::cerr << MTracer::dump_string(); } while (false)
#else
#define MTRACER ((void)0) #define MTRACER_DUMP_STRING \ std::string("\nMTracer: Define USE_MTRACER to use MTracer.\n") #define MTRACER_DUMP ((void)0)
#endif
|
测试代码如下 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| #define USE_MTRACER
#include "mtracer.hpp" #include <iostream>
class A { public: static void Fun() { MTRACER; std::cerr << MTRACER_DUMP_STRING; }
static void Fun2() { MTRACER;
[[maybe_unused]] double value = [](double max_value) { double s = 0; int n = 1; while (s < max_value) { s += (1.0 / n); ++n; } return s; }(20);
Fun(); }
static void Fun3() { MTRACER;
[[maybe_unused]] double value = [](double max_value) { double s = 0; int n = 1; while (s < max_value) { s += (1.0 / n); ++n; } return s; }(40);
Fun2(); } };
int main() { MTRACER;
A::Fun3();
return 0; }
|
运行结果如下 1 2 3 4 5 6
| Call stack (MTRACER): 3: .../mtracer_demo.cpp:9 static void A::Fun() 2: .../mtracer_demo.cpp:14 static void A::Fun2() 1: .../mtracer_demo.cpp:30 static void A::Fun3() 0: .../mtracer_demo.cpp:47 int main()
|