C中虚拟内存的组织

时间:2015-03-22 16:02:32

标签: c variables virtual-memory

对于以下各项,它似乎存储在内存中的位置,顺序如下:全局变量局部变量静态局部变量函数参数全局常量本地常量函数本身(并且是主要特殊情况?),动态分配变量

我将如何通过实验来评估,即使用C代码?

我知道 全局变量 - 数据
静态变量 - 数据
常数数据类型 - 代码
局部变量(在函数中声明和定义) - 堆栈
在main函数中声明和定义的变量 - 堆栈
指针(例如:char *arr,int *arr) - 数据或堆栈
动态分配空间(使用malloc,calloc) - 堆

2 个答案:

答案 0 :(得分:1)

您可以编写一些代码来创建上述所有内容,然后打印出他们的地址。例如:

void func(int a) {
    int i = 0;
    printf("local i address is %x\n", &i);
    printf("parameter a address is %x\n", &a);
}

printf("func address is %x\n", (void *) &func);

注意函数地址有点棘手,你必须把它转换为void *当你取一个函数的地址时你省略了()。比较内存地址,您将开始获取图片或事物的位置。通常文本(指令)位于底部(最接近0x0000),堆位于中间,堆栈从顶部开始向下增长。

答案 1 :(得分:0)

理论上

就内存位置而言,指针与其他变量没有区别。

可以在堆栈上或直接在寄存器中分配局部变量和参数。

常量字符串将存储在特殊数据部分中,但基本上与数据位置相同。

数值常量本身不会存储在任何地方,它们将被放入其他变量或直接转换为CPU指令 例如int a = 5;将常量5存储到变量a中(实际内存与变量绑定,而不是常量),但a *= 5将生成乘以{{}的必要代码。 1}}由常数5。

就内存位置而言,

a只是一个函数。本地main变量与任何其他本地变量没有区别,main代码位于代码部分的某个位置,就像任何其他函数一样,mainargc只是像任何参数一样的参数其他(它们由调用argv的启动代码提供)等等。

代码生成

现在,如果你想看看编译器和运行时放置所有这些东西的位置,可能就是编写一个小程序来定义其中的几个,并要求编译器生成一个汇编列表。然后,您将看到每个元素的存储方式。

对于堆数据,您将看到对malloc的调用,它负责与动态内存分配器连接。

对于堆栈数据,您将看到对堆栈指针(x86架构上的ebp寄存器)的奇怪引用,它们将用于参数和(自动)局部变量。

对于全局/静态数据,您将看到以变量命名的标签。

常量字符串可能会标记一个糟糕的名称,但您会注意到它们都会进入一个将在数据旁边链接的部分(通常名为bss)。

运行时地址

或者,您可以运行此程序并要求它打印每个元素的地址。但是,这不会显示寄存器的使用情况。

如果使用变量地址,则会强制编译器将其放入内存中,否则可能会将其保存到寄存器中。

另请注意,内存组织依赖于编译器和系统。使用gcc和MSVC编译的相同代码可能具有完全不同的地址和元素。

代码优化器也可能做一些奇怪的事情,所以我建议先编译你的示例代码,先禁用所有优化。
看看编译器如何获得大小和/或速度可能会很有趣。