StackWalk64
#include <Windows.h> #define PULONG_PTR ULONG**
#define PULONG ULONG*
#define ULONG_PTR ULONG*
#include <DbgHelp.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h> // 添加对dbghelp.lib的编译依赖
//
#pragma comment(lib, "dbghelp.lib")
const int MAX_ADDRESS_LENGTH = ;
const int MAX_NAME_LENGTH = ;
// 崩溃信息
//
// 安全拷贝字符串函数
//
// 得到程序崩溃信息
// // 得到CallStack信息
//
#define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS (0x04) // lpModuleName是模块中的一个地址
typedef BOOL (WINAPI* GetModuleHandleExA_T)(
DWORD dwFlags,
LPCSTR lpModuleName,
HMODULE* phModule
);
HMODULE getmodulename(char* buffer,int size,void* addri)
{
HMODULE hmodule;
char FileName[MAX_PATH] = {};
GetModuleHandleExA_T GetModuleHandleExA=(GetModuleHandleExA_T)GetProcAddress(GetModuleHandle("kernel32.dll"),"GetModuleHandleExA");
GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCSTR)addri, &hmodule);
GetModuleFileNameA(hmodule, buffer, size);
return hmodule;
}
char* gettimestring(char* buffer)
{
SYSTEMTIME systemtime;
GetSystemTime( &systemtime);
sprintf(buffer,"[%2.2d.%2.2d]",systemtime.wHour,systemtime.wMinute,systemtime.wSecond,systemtime.wMilliseconds);
return buffer;
}
void log(const char*format,...)
{
va_list v;
char buffer[];
char tbuffer[];
va_start(v,format);
_vsnprintf(buffer,,format,v);
va_end(v);
char fname[];
sprintf(fname,"%d.txt",GetCurrentThreadId());
FILE* fd = fopen(fname,"a+b");
fprintf(fd," %s[%d.%d]%s\r\n",gettimestring(tbuffer),GetCurrentProcessId(),GetCurrentThreadId(),buffer);
fclose(fd);
//OutputDebugStringA(buffer);
}
void logthread(DWORD threadid,const char*format,...)
{
va_list v;
char buffer[];
char tbuffer[];
va_start(v,format);
_vsnprintf(buffer,,format,v);
va_end(v);
char fname[];
sprintf(fname,"%d.txt",threadid);
FILE* fd = fopen(fname,"a+b");
fprintf(fd," %s[%d.%d]%s\r\n",gettimestring(tbuffer),GetCurrentProcessId(),GetCurrentThreadId(),buffer);
fclose(fd);
//OutputDebugStringA(buffer);
}
void PrintCallStackFromContext(const CONTEXT *pContext,HANDLE hThread,DWORD dwThreadId) ;
typedef HANDLE (WINAPI * OPENTHREADFUN)(DWORD dwDesiredAccess,BOOL bInheritHandle,DWORD dwThreadId);
DWORD WINAPI __printstack(void* p)
{
DWORD dwThreadId = (DWORD)p;
DWORD error;
//1:kernel32 大部分程序都自动加载了kernel32.dll 所以再获得句柄之前不需要Loadlibray
HMODULE hKernel32 = ::GetModuleHandle("kernel32.dll");
//2获得函数指针
OPENTHREADFUN pFun = (OPENTHREADFUN)GetProcAddress(hKernel32,"OpenThread");
HANDLE hThread = pFun(THREAD_GET_CONTEXT,,dwThreadId);
if(hThread==){
error = GetLastError();
::MessageBox(,"error1",,);
return -;
}
CONTEXT tagContext;
tagContext.ContextFlags = CONTEXT_FULL;
if(GetThreadContext(hThread,&tagContext)){
PrintCallStackFromContext(&tagContext,hThread,dwThreadId);
}else{
error = GetLastError();
::MessageBox(,"error2",,);
return -;
}
return ;
}
void PrintCurrentCallStack()
{
HANDLE hThread = CreateThread(,,__printstack,(void*)GetCurrentThreadId(),,);
WaitForSingleObject(hThread,-);
}
void PrintCallStackFromContext(const CONTEXT *pContext,HANDLE hThread,DWORD dwThreadId)
{
HANDLE hProcess = GetCurrentProcess();
CONTEXT c = *pContext;
STACKFRAME64 sf;
memset(&sf, , sizeof(STACKFRAME64));
DWORD dwImageType = IMAGE_FILE_MACHINE_I386;
// 不同的CPU类型,具体信息可查询MSDN
//
#ifdef _M_IX86
sf.AddrPC.Offset = c.Eip;
sf.AddrPC.Mode = AddrModeFlat;
sf.AddrStack.Offset = c.Esp;
sf.AddrStack.Mode = AddrModeFlat;
sf.AddrFrame.Offset = c.Ebp;
sf.AddrFrame.Mode = AddrModeFlat;
#elif _M_X64
dwImageType = IMAGE_FILE_MACHINE_AMD64;
sf.AddrPC.Offset = c.Rip;
sf.AddrPC.Mode = AddrModeFlat;
sf.AddrFrame.Offset = c.Rsp;
sf.AddrFrame.Mode = AddrModeFlat;
sf.AddrStack.Offset = c.Rsp;
sf.AddrStack.Mode = AddrModeFlat;
#elif _M_IA64
dwImageType = IMAGE_FILE_MACHINE_IA64;
sf.AddrPC.Offset = c.StIIP;
sf.AddrPC.Mode = AddrModeFlat;
sf.AddrFrame.Offset = c.IntSp;
sf.AddrFrame.Mode = AddrModeFlat;
sf.AddrBStore.Offset = c.RsBSP;
sf.AddrBStore.Mode = AddrModeFlat;
sf.AddrStack.Offset = c.IntSp;
sf.AddrStack.Mode = AddrModeFlat;
#else
#error "Platform not supported!"
#endif
//HANDLE hThread = GetCurrentThread();
logthread(dwThreadId,"=====stackwalk64=====");
while (true)
{
// 该函数是实现这个功能的最重要的一个函数
// 函数的用法以及参数和返回值的具体解释可以查询MSDN
//
if (!StackWalk64(dwImageType, hProcess, hThread, &sf, &c, NULL, , , NULL))
{
break;
}
if (sf.AddrFrame.Offset == )
{
break;
}
// 得到函数名
//
DWORD retaddress = (DWORD)sf.AddrPC.Offset;
char buffer[];
HMODULE hmod = getmodulename(buffer,,(void*)retaddress);
logthread(dwThreadId,"retaddress=%s %x",buffer,retaddress-(DWORD)hmod);
}
logthread(dwThreadId,"==========");
}
StackWalk64的更多相关文章
- 《Note --- Unreal --- MemPro (CONTINUE... ...)》
Mem pro 是一个主要集成内存泄露检测的工具,其具有自身的源码和GUI,在GUI中利用"Launch" button进行加载自己待检测的application,目前支持的平台为 ...
- 《Walking the callstack(转载)》
本文转载自:https://www.codeproject.com/articles/11132/walking-the-callstack Download demo project with so ...
- Google之Chromium浏览器源码学习——base公共通用库(四)
本文将介绍debug调试相关的内容,包括调试器.性能分析.堆跟踪.跟踪事件等: alias.h:Alias函数,提供防止载微软的编译器优化某参数变量的操作,内部通过#pragma optimize(& ...
- 【转】调试Release发布版程序的Crash错误
http://www.cppblog.com/Walker/archive/2012/11/08/146153.html http://blog.sina.com.cn/s/blog_48f93b53 ...
- 使用Visual Leak Detector检测内存泄漏[转]
1.初识Visual Leak Detector 灵活自由是C/C++语言的一大特色,而这也为C/C++程序员出了一个难题.当程序越来越复杂时,内存的管理也会变得越加复杂,稍有不慎就会出现内存问题 ...
- VLD(Visual LeakDetector)内存泄露库的使用
VLD简介 由于C/C++语言没有所谓的垃圾收集器,内存的分配和释放都需要程序员自己来控制,这会给C/C++程序员带来一定的困难.当您的程序越来越复杂时,它的内存管理也会变得越来越困难.内存泄漏.内存 ...
- [转]让程序在崩溃时体面的退出之CallStack
原文地址:http://blog.csdn.net/starlee/article/details/6618849 在我的那篇<让程序在崩溃时体面的退出之Unhandled Exception& ...
- 内存泄漏工具VLD1.0_要点分析
0X01 关闭FPO优化 // Frame pointer omission (FPO) optimization should be turned off for this // entire fi ...
- vld(Visual Leak Detector) 内存泄露检测工具
初识Visual Leak Detector 灵活自由是C/C++语言的一大特色,而这也为C/C++程序员出了一个难题.当程序越来越复 杂时,内存的管理也会变得越加复杂,稍有不慎就会出现内存问题.内存 ...
随机推荐
- Java序列化(含transient)
什么是序列化? 我们创建的对象只有在Java虚拟机保持运行时,才会存在于内存中.如果想要超出Java虚拟机的生命周期,就可以将对象序列化,将对象状态转换为字节序列,写入文件(或socket传输),后面 ...
- 快速排序 O(n logn) 堆排序 O(n logn) 归并排序 O(n logn)
NB三人组 快速排序 思路" 取一个元素P (第一个元素), 使元素归位 列表被P 分成两部分,左边都比P小,右边比P大; 递归完成排序. 问题 如果是已经排序好的 倒叙 列表 则会 递归深 ...
- Linux中的零拷贝技术
转载:https://www.jianshu.com/p/fad3339e3448 引文## 在写一个服务端程序时(Web Server或者文件服务器),文件下载是一个基本功能.这时候服务端的任务是: ...
- 让你提前认识软件开发(21):C程序中的定时器
版权声明:本文为博主原创文章.对文章内容有不论什么意见或建议.欢迎与作者单独交流.作者QQ(微信):245924426. https://blog.csdn.net/zhouzxi/article/d ...
- centos7下安装docker(18docker日志---docker logs)
在微服务架构中,由于容器的数量众多以及快速变化的特性使得记录日志和监控变得越来越重要,考虑到容器的短暂和不固定周期,当我们需要排查问题的时候容器可能不在了.因此,一套集中式的日志管理系统是生产环境中不 ...
- redis的过期时间和过期删除机制
一:设置过期时间 redis有四种命令可以用于设置键的生存时间和过期时间: EXPIRE <KEY> <TTL> : 将键的生存时间设为 ttl 秒 PEXPIRE <K ...
- springBoot 搭建web项目(前后端分离,附项目源代码地址)
springBoot 搭建web项目(前后端分离,附项目源代码地址) 概述 该项目包含springBoot-example-ui 和 springBoot-example,分别为前端与后端,前后端 ...
- D. Zero Quantity Maximization(hash+map)
题意:就是让c=a*x+b,给你一个a[],b[],让你尽可能多的让c[]=0,输出有多少. 思路:直接令c=0,则x=-b/a, 也就是一条直线,通过这样就用hash值使相同的k值映射到一起,使用了 ...
- mysql执行顺序
SELECT语句执行顺序 SELECT语句中子句的执行顺序与SELECT语句中子句的输入顺序是不一样的,所以并不是从SELECT子句开始执行的,而是按照下面的顺序执行: 开始->FROM子句-& ...
- 1043. 输出PATest(20)
1043. 输出PATest(20) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 给定一个长度不超过10000 ...