首页
社区
课程
招聘
[原创]软件调试基础--07用户态栈回溯数据库UST
发表于: 2016-1-27 15:08 4577

[原创]软件调试基础--07用户态栈回溯数据库UST

2016-1-27 15:08
4577

在程序中,我们最常使用的堆内存和栈内存,都有一定的保护机制和调试支持。了解这些特性,对我们后续解决软件问题有很大帮助。这节,我们讲解堆内存的一个重量级调试支持--用户态栈回溯数据库(User Mode Stack Trace Database,简称UST)。

很多时候,我们程序出现问题,是在堆内存上发生的,如果此时,我们能拿到发生问题这个堆,是在哪个函数里的哪行代码分配的,可能对我们分析问题很有帮助,最好的情况下,能拿到这个堆内存分配时的完整调用堆栈,那就更好了。本节的用户态栈回溯数据库,就是为了完成这个功能而设计的。

这个功能,是操作系统为我们提供的,当程序执行时,操作系统记录下当前进程创建堆内存时的完整堆栈,便于我们后续分析时,回顾某内存当时被创建时的调用堆栈。讲了这么多,你应该很容易想到这个东西的一个应用场景了。没错,解决内存泄露!

下面还是以例子来说明问题。代码如下:

void test1()

{

    char *p = new char[100];

char szAddress[32] = { 0 };

sprintf(szAddress, "%p", p);

OutputDebugString(szAddress);

}

void test2()

{

    printf("test2\n");

}

int _tmain(int argc, _TCHAR* argv[])

{

    test1();

    test2();

     

    system("pause");

    return 0;

}

编译链接之后,我们来调试这个程序,调试环境,符号设置之类的东西,我就不再重复了。我们在test2函数入口处下断点,此时test1被调用的过程早已经完成,但此时,我们想看那个100字节当时分配时的执行情景(调用堆栈)。那就需要操作系统为我们记录下,堆内存分配时的用户态栈回溯数据库了。

使用gflags有界面版,来为CodeTest.exe进行开启UST,如下图:



也可以用命令行版,来开启,具体方法请自行百度!

然后我们就可以开始调试了,有了前面的基础,我就直接上图了,请原谅我的直接^_^

  

流程就是这样了。程序中,我们加入了一个输出,输出那100字节的堆内存的首地址,方便我们调试时候,打印这个内存分配时的调用堆栈。到这里,我们想想,假如我们能找到程序中,内存泄露的地址,再加上这个功能,那就很容易找到内存泄露的源码位置了。后面我会介绍,怎么找到发生内存泄露的内存的首地址。


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 3
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//