本机堆分配的运行时类型标识的制作方法

文档序号:6378530阅读:195来源:国知局
专利名称:本机堆分配的运行时类型标识的制作方法
技术领域
本发明涉及存储器管理技术,更具体地,涉及本机堆分配的运行时类型标识。
背景技术
存储器管理包括根据请求将存储器的各部分分配给各程序,以及当程序不再需要所分配的存储器时释放该存储器以供重新使用。对存储器的低效或不正确的使用会降低程序性能或导致程序崩溃。类似的,无法释放已分配的存储器或不正确地释放存储器会降低程序性能或导致程序崩溃。术语“垃圾回收”常被用来表示一种自动存储器管理形式,其中垃圾回收器重新声明不再是使用中的存储器。垃圾回收是一种被频繁用于虚拟机环境中的技术。与之相比,手动存储器管理依赖于在程序中使用用于请求操作系统分配存储器和取消分配未被使用的存储器的指令。普遍使用的用于手动地管理存储器的语言包括本机语言,诸如C和C++。手动存储器管理会将几个常见类的错误引入程序中。例如,如果当程序使用完所分配的存储器部分时其没有被释放,则会发生存储器泄露。存储器泄露可以是相对无害的(例如,在短时运行的程序中,其中程序结束时操作系统取消分配程序资源),或者如果存储器泄露用尽了可用存储器则会导致程序崩溃。即使存储器泄露没有用尽可用存储器并且没有导致程序崩溃,程序性能会被降低,因为例如缺少足够的可用存储器使数据被强制交换出到磁盘。当分配的空间被释放不止一次时或者如果释放了指向未分配存储器的指针,会发生另一种类型的存储器管理错误。这类错误会损坏数据结构或者会不正确地释放后来已由另一程序构造使用的部分存储器。如果在存储器被释放后使用了指向被释放的存储器的指针,则接着会发生无法预料的结果。当程序中的指令分配过多存储器使得没有剩余足够的存储器以供程序高效运行时,会发生存储器过度使用。

发明内容
可请求执行中的本机程序的快照并且可提供对快照请求时所分配的用户类型的存储器分配统计。通过使用静态调试信息和动态运行时分配信息,活(live)存储器堆分配可使用用户类型信息来增强。用户类型和堆信息可被用于计算存储器分配的大小并聚集用户类型实例的计数和大小。使用静态调试信息,可计算和显示引用图,该引用图显示活实例中的对象的嵌套。可提供源文件的名称以及调用存储器分配函数的指令的行号。提供发明内容述以便以简化形式介绍将在以下详细描述中进一步描述的一些概念。本发明内容并不旨在标识所要求保护主题的关键特征或必要特征,也不旨在用于限制所要求保护主题的范围。


在附图中图1a示出了根据此处所公开的主题的各方面的捕捉相对虚拟地址(RVA)至类型信息的系统100的示例;图1b示出了根据此处所公开的主题的各方面的将RVA映射成类型的表110的示例;图1c示出了根据此处所公开的主题的各方面的捕捉运行时存储器分配信息的系统101的示例;图1d示出了根据此处所公开的主题的各方面的将分配的实例的地址映射成调用存储器分配函数的指令的虚拟地址的表134的示例;图1e示出了根据此处所公开的主题的各方面的潜在的实例参考信息的表140的示例,其中潜在的实例参考中的一些已被标识为非指针;图1f示出了根据此处所公开的主题的各方面的包括类型信息的潜在的实例参考信息的表176的不例;图2a示出了根据此处所公开的主题的各方面的计算目标进程的存储器分配统计的的方法200的示例;图2b示出了根据此处所公开的主题的各方面的目标进程的经计算出的存储器分配统计的的显示230的示例;

图3是根据本文所公开主题的各方面的计算环境的示例的框图;以及图4是根据此处所公开的主题的各方面的集成开发环境的示例的框图。
具体实施方式
概览用于用本机代码编写的程序的已知工具可提供诸如“在点A处,进程B已分配了起始于地址D的C个字节的存储器”之类的信息。然而,已知工具不能够提供与所分配的存储器块相关联的用户类型信息。即,已知工具不能提供诸如“在点A处,进程B已为用户类型为F的对象的E个实例分配了起始于地址Dp…D1J^C个字节的存储器”之类的信息。根据此处所描述的主题的各方面,提供了可将用户类型信息与存储器中特定位置处分配的存储器块相关联的工具。信息可被聚集和概括,并被提供在显示中。所提供的信息可帮助用户确定多少存储器被分配给哪些用户类型。这进而可帮助用户诊断存储器过度使用以及本机源代码中的其它存储器分配模式。想要用户类型存储器分配统计的本机源程序可被编译以生成二进制文件(例如,可执行文件或动态链接库)。根据此处所描述的主题的各方面,其执行导致分配存储器的二级制文件中的指令的相对虚拟地址(RVA)可被映射到该RVA处的指令所分配的实例的类型或与该类型相关联。当执行该二级制文件时,截取对存储器分配的请求的程序模块可被插入到二进制文件正执行于的目标进程中。所插入的程序模块可截取对发生在目标进程内的已知存储器分配函数的调用。当程序运行及分配发生时,可记录调用存储器分配函数的指令的虚拟地址(在此称为调用点)。新创建的实例的虚拟存储器地址也可被记录并被映射到调用了存储器分配函数的指令的虚拟地址或与该虚拟地址相关联。响应于接收到对堆快照的请求,可通过走查与进程相关联的一个或多个堆来标识目前为止在该进程中所作出的所有存储器分配。调用存储器分配函数的每个指令的虚拟地址可以被转换成RVA。这一 RVA可以被匹配于之前创建的(例如,在编译期间)RVA/类型表中对应的RVA,以确定在二级制文件的执行期间所分配的实例的用户类型。与所分配的实例的虚拟存储器地址相关联的实例的类型可通过将调用点(曾调用存储器分配函数的指令的虚拟地址)转换成其执行导致分配存储器的二级制文件中的指令的RVA来确定。为了将调用点转换成RVA,进程存储器中加载二级制文件所位于的基地址可从调用点减去。与前一步骤(例如编译步骤)中的匹配RVA相关联的用户类型可被分配给调用点。特定用户类型的信息可被聚集、概括并显示。所显示的信息可包括类型、所分配的实例的总数以及特定类型的实例的经聚集的大小、以及该类型的定义的位置。所显示的信息可还包括一种类型的每个实例的分解、实例的大小、创建该实例的模块、该实例的分配点、以及源文件的名称以及分配该实例的指令的行号。可提供描述引用关系的引用图。引用图信息可通过扫描进程堆以查找潜在的指针来获取,其中扫描通过查找并记录所有的指针大小的字段来进行。可通过使用用来确定每个潜在指针的类型的静态调试信息并且删除非指针类型来删除被记录的非指针字段。即,根据此处所描述的主题的各方面,响应于接收对快照的请求,进程堆可被扫描以查找潜在的指针的实例。任何具有指针大小的长度的虚拟地址可被记录。可以理解的是不是所有指针大小的实体都有可能是真正的指针。提供对象布局的符号调试信息可被用于移除不是指针的被记录的指针大小的偏移。例如,假设程序包括对象Foo,其包括另一对象Bar。从编译中产生的调试文件中获取的对象Foo的布局可因此包括指向对象Bar的指针。显示对象Foo和Bar之间的嵌套关系的引用图可随后被显示。本机堆分配的运行时类型标识图1a示出了根据此处所公开的主题的各方面的捕捉RVA至类型匹配信息的系统100的示例。系统100的全部或某些部分可以驻留在诸如下面参考图3所描述的计算机之类的一个或多个计算机上。系统100可在诸如参考图4所描述的软件开发计算机之类的软件开发计算机上执行。系统100或其部分可在诸如IDE 104之类的IDE内执行或者在IDE之外执行。IDE可以是诸如参考图4所描述的IDE之类的IDE,或者可以是支持本机语言的任何其它IDE。系统100的全部或部分可被实现为插件或扩展。系统100可包括诸如计算机102之类的一个或多个计算机或计算设备,其包括诸如处理器142等之类的一个或多个处理器、诸如存储器144之类的存储器、和/或诸如映射模块116之类的一个或多个模块。系统100可还包括诸如编译器106之类的编译器。编译器106可以是C或C++编译器或其中实现手动存储器分配的任何其他本机编程语言编译器。根据此处所公开的主题的各方面,映射模块11 6可以是编译器106的一部分或者可以是独立的模块(未示出)。映射模块116可收集诸如RVA/类型信息110之类的RVA至类型信息。映射模块116可在源程序114的编译期间将诸如RVA/类型信息110之类的RVA至类型信息收集到动态链接库或诸如可执行文件108之类的可执行文件中。可替换地,映射模块116可在编译进程之外执行。当编译进行时,可收集诸如调试信息112之类的调试信息。调试信息可包括程序模块中的所有符号的列表。调试信息可包括符号的地址、其中声明了该符号的源文件的名称以及其中声明了该符号的源文件中的行的行号。调试信息可以存储在程序数据库文件中,这是一种由微软公司开发的、用于存储关于程序的、通常具有.Pdb扩展名的调试信息的专有文件格式。可替换地,调试信息可以存储在二级制文件本身中。
典型编译器的前端执行语法和语义检查并报告错误。前端可生成源代码的中间表示或IR以供中间端处理。在中间端,可进行优化转换并生成第二 IR。后端通常将来自中间端的IR转换成汇编码。在前端编译期间,通常创建抽象语法树(AST)。AST是源代码的抽象语法结构的树形表示,其中树的每个节点表示源代码中的一个构造。根据此处所公开的主题的各方面,后端代码生成器可使用AST来将存储器分配指令的相对虚拟地址(RVA)映射到那些指令所分配的类型。因此,将RVA映射成类型的信息可由编译器在编译期间计算,并且被包括作为程序的调试数据库的一部分(例如,在.PDB文件中或在二进制文件本身中)。当在运行时发生存储器分配时,这一信息允许基于地址的类型查找,如以下更全面描述的。例如,在以下的C++代码中,创建从编译器生成的汇编指令的RVA到类型Foo的
(静态)符号调试信息的映射。
权利要求
1.一种系统,包括 计算设备的至少一个处理器; 所述计算设备的存储器;以及 加载到所述存储器中的至少一个模块,所述模块使所述至少一个处理器 响应于接收对堆快照的请求,通过以下步骤提供本机语言程序的存储器分配统计接收将所述本机语言程序的二进制文件中的指令的相对虚拟地址映射到用户类型的信息,所述指令在被执行时请求存储器分配; 将进程中执行的指令的虚拟存储器地址映射到所述指令所请求的存储器分配的实例的地址; 将所述指令的虚拟存储器地址匹配于所述指令的对应的相对虚拟地址; 将被映射到对应的相对虚拟地址的用户类型分配给所述指令的虚拟存储器地址;以及 聚集用户类型实例计数和大小。
2.如权利要求1所述的系统,其特征在于,还包括 加载到所述存储器中的至少一个模块,所述模块使所述至少一个处理器 通过以下步骤显示引用图 扫描所述进程的进程堆以查找指针大小的字段的实例; 移除非指针的指针大小的字段;以及 显示所述引用图中的存储器分配实例之间的关系。
3.如权利要求1所述的系统,其特征在于,还包括 加载到所述存储器中的至少一个模块,所述模块使所述至少一个处理器 在编译期间将所述本机语言程序的二进制文件中的指令的相对虚拟地址映射到所述用户类型。
4.如权利要求2所述的系统,其特征在于,在编译期间生成的符号调试信息提供实例的布局,其中所述布局被用于移除被记录的指针大小的、但不是指针的字段。
5.如权利要求2所述的系统,其特征在于,用户类型和进程堆信息被用于计算存储器分配的大小并聚集用户类型实例计数和大小。
6.一种方法,包括 将本机语言程序的指令的相对虚拟地址映射到用户类型,所述指令调用存储器分配函数; 将追踪模块插入目标进程,所述目标进程在计算设备的处理器上执行所述指令; 截取对所述存储器分配函数的调用并记录所述存储器分配函数的返回地址; 记录由所述存储器分配函数在存储器中分配的实例的地址; 将所述返回地址转换成对应的相对虚拟地址; 将所记录的返回地址分配给所述用户类型;以及 提供聚集的存储器分配的大小以及用户类型实例计数和大小。
7.如权利要求6所述的方法,其特征在于,还包括 通过以下步骤显示引用图 扫描所述实例的进程堆以查找指针大小的字段的实例; 移除非指针的指针大小的字段;以及显示所述弓I用图中的实例之间的关系。
8.如权利要求6所述的方法,其特征在于,通过走查抽象语法树以及将相对虚拟地址/用户类型映射信息写入与编译期间生成的静态调试文件分开的文件中,所述指令的相对虚拟地址到用户类型的映射与编译分开地进行。
9.如权利要求6所述的方法,其特征在于,存储器分配和用户类型实例计数和大小按照类型、模块、源文件、名字空间或类名来提供。
10.一种包括当执行时使计算设备的至少一个处理器执行下列操作的计算机可执行指令的计算机可读存储介质 接收静态调试信息,所述静态调试信息包括将本机程序的二进制文件的指令的相对虚拟地址映射到与所述指令相关联的用户类型的表,所述指令在执行时请求存储器分配;在进程中执行所述本机程序; 将所述进程的进程堆中的指令的虚拟存储器地址映射到所述存储器分配的实例的地址; 将所述指令的虚拟存储器地址匹配于所述指令的对应的相对虚拟地址; 将被映射到对应的相对虚拟地址的用户类型分配给所述指令的虚拟地址; 响应于接收对进程堆快照的请求,通过以下步骤创建引用图 扫描进程堆以查找指针大小的字段的实例; 移除非指针的指针大小的字段;以及 显示所述引用图,聚集用户类型实例计数和大小。
全文摘要
本发明涉及本机堆分配的运行时类型标识。在编译期间,创建了将本机语言程序的存储器分配指令的相对虚拟地址映射到实例的用户类型的表。在程序的执行期间,被插入到进程中的模块截取对存储器分配函数的调用并记录调用存储器分配函数的指令的虚拟地址和所创建的实例的虚拟地址。当请求进程堆的快照时,对应编译时指令的用户类型被分配给所创建的实例。用户类型和堆信息可被用于计算存储器分配的大小并聚集用户类型实例的计数和大小。使用静态调试信息,可计算和显示引用图,该引用图显示活实例中的对象的嵌套。
文档编号G06F11/14GK103034484SQ20121038086
公开日2013年4月10日 申请日期2012年10月9日 优先权日2011年10月10日
发明者C·施米希, A·R·鲁滨逊 申请人:微软公司
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1