转自:http://blog.csdn.net/anonymousrookie/article/details/51813418
有些时候为了便于调试,我们需要记录函数调用的堆栈信息。为此,封装了一个类StackDumper,在相应的函数中调用该类的成员函数即可。
stack_dumper.h
#ifndef STACK_DUMPER_H
#define STACK_DUMPER_H
#ifdef _WIN32
#include <windows.h>
#include <dbghelp.h>
#include <string>
#include <sstream>
#pragma comment (lib, "dbghelp.lib")
#endif // _WIN32
class StackDumper {
public:
StackDumper();
~StackDumper();
void Destory();
std::string DumpStack();
private:
#ifdef _WIN32
UINT max_name_length_;
CONTEXT context_;
STACKFRAME64 stackframe_;
HANDLE process_, thread_;
PSYMBOL_INFO symbol_;
IMAGEHLP_LINE64 source_info_;
DWORD displacement_;
#endif // _WIN32
std::ostringstream stack_info_str_stream_;
};
#endif // STACK_DUMPER_H
- 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
- 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
stack_dumper.cpp
#include "stack_dumper.h"
StackDumper::StackDumper() {
#ifdef _WIN32
enum { MAX_NAME_LENGTH = 256 };
symbol_ = (PSYMBOL_INFO)malloc(sizeof(SYMBOL_INFO)+(MAX_NAME_LENGTH - 1) * sizeof(TCHAR));
memset(symbol_, 0, sizeof(SYMBOL_INFO)+(MAX_NAME_LENGTH - 1) * sizeof(TCHAR));
symbol_->SizeOfStruct = sizeof(SYMBOL_INFO);
symbol_->MaxNameLen = MAX_NAME_LENGTH;
memset(&source_info_, 0, sizeof(IMAGEHLP_LINE64));
source_info_.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
RtlCaptureContext(&context_);
memset(&stackframe_, 0, sizeof(STACKFRAME64));
stackframe_.AddrPC.Offset = context_.Eip;
stackframe_.AddrPC.Mode = AddrModeFlat;
stackframe_.AddrStack.Offset = context_.Esp;
stackframe_.AddrStack.Mode = AddrModeFlat;
stackframe_.AddrFrame.Offset = context_.Ebp;
stackframe_.AddrFrame.Mode = AddrModeFlat;
stack_info_str_stream_.str("");
process_ = GetCurrentProcess();
thread_ = GetCurrentThread();
if (!SymInitialize(process_, NULL, TRUE)) {
stack_info_str_stream_ << "Initialize dbghelp library ERROR!\n";
}
#endif
}
StackDumper::~StackDumper() {
Destory();
}
void StackDumper::Destory() {
SymCleanup(process_);
free(symbol_);
stack_info_str_stream_ << "StackDumper is cleaned up!\n";
}
std::string StackDumper::DumpStack() {
#ifdef _WIN32
stack_info_str_stream_ << "Call stack: \n";
while (StackWalk64(IMAGE_FILE_MACHINE_I386, process_, thread_, &stackframe_,
&context_, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL)) {
if (stackframe_.AddrFrame.Offset == 0) {
break;
}
if (SymFromAddr(process_, stackframe_.AddrPC.Offset, NULL, symbol_)) {
stack_info_str_stream_ << " ==> " << symbol_->Name << "\n";
}
if (SymGetLineFromAddr64(process_, stackframe_.AddrPC.Offset, &displacement_, &source_info_)) {
stack_info_str_stream_ << "\t[" << source_info_.FileName << ":" << source_info_.LineNumber << "]\n";
}
else {
if (GetLastError() == 0x1E7) {
stack_info_str_stream_ << "\tNo debug symbol loaded for this function.\n";
}
}
}
#endif
return stack_info_str_stream_.str();
}
- 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
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 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
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
测试程序:
#include <iostream>
#include <string>
#include <sstream>
#include "stack_dumper.h"
#define LOG_DEBUG \
{ \
auto &str = StackDumper().DumpStack(); \
std::cout << str.c_str() << std::endl; \
}
int Func(int arc) {
LOG_DEBUG;
return arc;
}
void Show(const std::string& str) {
Func(11);
std::cout << str << std::endl;
}
void main() {
Show("AnonymousRookie...");
system("pause");
}
- 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
- 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
测试结果: