可视化计算/内存演化图
一位读者请求扩展此页面以包含更多内容。 你可以通过 添加新材料 (学习方法) 或在 阅览室 寻求帮助。 |
内存布局图 和 内存演化图 描述线性地址空间的内容,可以是某个时间点的快照,也可以是随时间变化的快照。
内存布局/演化图通常用于描述语言系统(编译器 和 解释器)。它们经常出现在编程语言概念、计算机硬件或编译器设计方面的本科课程中,例如在讨论 函数调用时的栈分配内存 或记录或数组在内存中的数据布局时。
内存布局图至少可以追溯到 绿龙书(Aho & Ullman 1977),该书展示了许多用于栈帧布局的 MLD(在第 10 章中);内存演化图最近被用来说明内存的使用和重用,以生成学生在复习讲义时可以理解的图表。
内存布局图 和 内存演化图 都提供有关计算机内存中值组织的信息,指示每个内存单元中包含的值。前者显示给定时刻内存内容的快照;后者显示内容随时间的演变。
如下所示,可以说明内存的各种不同用途,例如栈帧布局、数据结构组织、堆(自由存储)布局等。
根据需要,图可以显示带标签但没有值的抽象布局,也可以显示特定程序特定执行的内存映像,包括每个内存单元中的特定值。风格上的变化包括标签是在给定内存单元旁边还是在单元中写入。
内存布局图可以简单地是一组矩形,通常垂直堆叠,每个矩形对应于一个给定的内存单元或单元组。根据重点,布局图可以显示所有单元或只显示部分单元,并且可以显示每个字节或每个内存字。例如,为了说明使用栈帧来存放函数参数,使用这个示例 C++ 程序来计算一个数的幂
bool even(int i) { // return True iff i is an even number return i % 2 == 0; } double power(double base, int exp) { if (exp == 1) return base; else if (even(exp)) { double base_to_half_exp = power(base, exp/2); return base_to_half_exp * base_to_half_exp; } else return base * power(base, exp-1); } #include <iostream> int main() { std::cout << power(2, 10) << std::endl; }
我们可以为每个字画一个方框(对于双字画一个大方框),产生类似于以下的图表(例如,当我们检查 4 是否为偶数,以计算 power(2, 10) 时)--- 精心格式化和手绘的图像可能看起来像这样(手绘图像中可能令人困惑的划线和擦除是下面内存演化图的动机)
上面的示例显示了程序特定执行的特定值;绿龙书第 10 章中的图显示了相同主题的更抽象视图。
内存布局图经常用于讨论数据结构在内存中布局的选择。例如,Scott 的 编程语言实用 第 7.3 章展示了在内存中布局一个与下面几乎相同的结构的几种方法(带有一个示例 MLD,基于每个字段对齐到字的假设,并且“bool”值将存储在内存的 1 个字节中)。注意,Scott 的图比这里显示的图更抽象,因为它们不包含所有字段的特定值。
struct element { // similar to Ex. 7.35 of Scott's "Programming Language Pragmatics" (3rd ed). char name[2]; int atomic_number; double atomic_weight; bool metallic; }; struct element aluminum = {{'A', 'l'}, 13, 26.98, true };
内存演化图是一种系统地捕捉内存使用随时间变化的方法。可以将其视为一系列不同时间点的布局图,彼此对齐,例如随着时间的推移从左到右进行。通常,未更改的很大范围的值不会被复制,因此当某个单元没有显示值时,就会回看左侧。将下面的图表与上面的手绘图像进行对比 --- MED 即使是手绘的,也提供了对发生的事情的更易于理解的图像。(还要注意,这里的 MED 比上面的 MLD 显示了更多信息,因为它包含了帧指针和堆栈指针信息,以及一个额外的函数调用;将这些添加到上面的图片中会使清晰度上的差异更加明显。)