#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的更多相关文章

  1. 《Note --- Unreal --- MemPro (CONTINUE... ...)》

    Mem pro 是一个主要集成内存泄露检测的工具,其具有自身的源码和GUI,在GUI中利用"Launch" button进行加载自己待检测的application,目前支持的平台为 ...

  2. 《Walking the callstack(转载)》

    本文转载自:https://www.codeproject.com/articles/11132/walking-the-callstack Download demo project with so ...

  3. Google之Chromium浏览器源码学习——base公共通用库(四)

    本文将介绍debug调试相关的内容,包括调试器.性能分析.堆跟踪.跟踪事件等: alias.h:Alias函数,提供防止载微软的编译器优化某参数变量的操作,内部通过#pragma optimize(& ...

  4. 【转】调试Release发布版程序的Crash错误

    http://www.cppblog.com/Walker/archive/2012/11/08/146153.html http://blog.sina.com.cn/s/blog_48f93b53 ...

  5. 使用Visual Leak Detector检测内存泄漏[转]

      1.初识Visual Leak Detector 灵活自由是C/C++语言的一大特色,而这也为C/C++程序员出了一个难题.当程序越来越复杂时,内存的管理也会变得越加复杂,稍有不慎就会出现内存问题 ...

  6. VLD(Visual LeakDetector)内存泄露库的使用

    VLD简介 由于C/C++语言没有所谓的垃圾收集器,内存的分配和释放都需要程序员自己来控制,这会给C/C++程序员带来一定的困难.当您的程序越来越复杂时,它的内存管理也会变得越来越困难.内存泄漏.内存 ...

  7. [转]让程序在崩溃时体面的退出之CallStack

    原文地址:http://blog.csdn.net/starlee/article/details/6618849 在我的那篇<让程序在崩溃时体面的退出之Unhandled Exception& ...

  8. 内存泄漏工具VLD1.0_要点分析

    0X01 关闭FPO优化 // Frame pointer omission (FPO) optimization should be turned off for this // entire fi ...

  9. vld(Visual Leak Detector) 内存泄露检测工具

    初识Visual Leak Detector 灵活自由是C/C++语言的一大特色,而这也为C/C++程序员出了一个难题.当程序越来越复 杂时,内存的管理也会变得越加复杂,稍有不慎就会出现内存问题.内存 ...

随机推荐

  1. 持续集成-Jenkins安装部署

    1. 安装JDK[java8] 1.1. 软件安装 [yun@mini05 software]# pwd /app/software [yun@mini05 software]# .0_112.tar ...

  2. 在win7下python的xlrd和xlwt的安装于应用

    1. http://pypi.python.org/pypi/xlwt 和http://pypi.python.org/pypi/xlrd下载xlwt-0.7.4.tar.gz和xlrd-0.7.7. ...

  3. 模拟placeholder

    把这个记下来,主要是因为这里的 defaultValue 我之前竟然不知道 <input type="text" value="提示内容" onFocus ...

  4. Scrapy 框架 安装 五大核心组件 settings 配置 管道存储

    scrapy 框架的使用 博客: https://www.cnblogs.com/bobo-zhang/p/10561617.html 安装: pip install wheel 下载 Twisted ...

  5. 第二十六篇:USB3.0高带宽ISO(48KBytes/125us)实战

    USB3.1技术已经推出, 10Gbps的速率足以满足数据, HD视频传输的要求. 要步入USB3.1的研发, 还得将USB3.0的基础打扎实. 微软提供的SUPER MUTT仅仅包括一个接口0, 其 ...

  6. public private protected default

    public private protected default 这几个限定访问控制符只是在编译阶段起作用,在运行阶段不起作用 private修饰符 , 本类可以访问 default修饰符 , 本类, ...

  7. 使用chrome远程调试设备及调试模拟器设备

    使用chrome开发工具远程在Android上远程调试 准备工作 开始远程调试之前,需要做好如下准备: 在你电脑上安装Chrome 32 或者更新的版本 一根连接Android设备的USB线 手机系统 ...

  8. C#中webbrowser与javascript(js)交互的方法

    今天在做一个项目的时候需要用c#搞一个webbrowser,然后有些地方还需要与js交互.所以就查了一下资料,发现很多博客提到了但是却没有说下具体的操作.所以我就写一下. 开发环境是Visual St ...

  9. java让数字显示千分位 mark

    /** * 格式化数字为千分位显示: * @param 要格式化的数字: * @return */ public static String fmtMicrometer(String text) { ...

  10. mysql之grant权限说明

    mysql中给一个用户授权如select,insert,update,delete等其中的一个或者多个权限,主要使用grant命令,格式为: 给没有用户授权 grant 权限 on 数据库对象 to ...