程序对静态对象、自动对象和动态分配的对象使用不同的内存区域

  • 本文关键字:对象 内存 区域 静态 程序 动态分配 c
  • 更新时间 :
  • 英文 :


我正在关注"C Primer Plus">一书,遇到了一个理解记忆区域的问题。在书中,它指出:

通常,程序对静态对象、自动对象和动态分配的对象使用不同的内存区域。示例 12.15 说明了这一点。

// where.c -- where's the memory?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int static_store = 30;
const char * pcg = "String Literal";
int main(void)
{
int auto_store = 40;
char auto_string[] = "Auto char Array";
int *pi;
char *pcl;
pi = (int *) malloc(sizeof(int));
*pi = 35;
pcl = (char *) malloc(strlen("Dynamic String") + 1);
strcpy(pcl, "Dynamic String");
printf("static_store: %d at %pn", static_store, &static_store);
printf("  auto_store: %d at %pn", auto_store, &auto_store);
printf("         *pi: %d at %pn", *pi, pi);
printf("  %s at %pn", pcg, pcg);
printf(" %s at %pn", auto_string, auto_string);
printf("  %s at %pn", pcl, pcl);
printf("   %s at %pn", "Quoted String", "Quoted String");
free(pi);
free(pcl);
return 0;
}

运行代码并获取:

static_store: 30 at 0x10a621040
auto_store: 40 at 0x7ffee55df768
*pi: 35 at 0x7fbf1d402ac0
String Literal at 0x10a620f00
Auto char Array at 0x7ffee55df770
Dynamic String at 0x7fbf1d402ad0
Quoted String at 0x10a620f9b

这本书的结论是:

如您所见,静态数据(包括字符串文本(占用一个区域,自动数据占用第二个区域,动态分配的数据占用第三个区域(通常称为内存堆或可用存储(。

我可以弄清楚他们的地址不同。我如何确保他们来自不同的地区?

不同的地区有非常不同的地址。如果它们位于同一区域,则它们将具有相似的地址。更好的例子,我们在每个区域中分配 2 个对象:

#include <stdio.h>
#include <stdlib.h>
int main (void)
{
int stack1;
int stack2;
static int bss1;
static int bss2;
static int data1=1;
static int data2=1;
int* heap1 = malloc(1);
int* heap2 = malloc(1);  
char* rodata1 = "hello";
char* rodata2 = "world";
printf(".stackt%p %pn",  &stack1,  &stack2);
printf(".bsst%p %pn",    &bss1,    &bss2);
printf(".datat%p %pn",   &data1,   &data2);
printf(".heapt%p %pn",   heap1,    heap2);
printf(".rodatat%p %pn", rodata1,  rodata2);
free(heap1);
free(heap2);
}

输出(例如(:

.stack  000000000022FE2C 000000000022FE28
.bss    0000000000407030 0000000000407034
.data   0000000000403010 0000000000403014
.heap   0000000000477C50 0000000000477C70
.rodata 0000000000404000 0000000000404006

如您所见,同一段中的两个变量具有几乎相同的地址,唯一的区别是对象的大小(可能还有一些对齐空间(。虽然与其他段中的变量相比,它们的地址非常不同。

C 标准规定,一个对象可以有 4 种不同的存储持续时间之一。 这些是:

  • 静态的
  • 自动
  • 分配
  • 线

上面的代码解决了其中的前 3 个问题。

静态对象是使用static修饰符在文件范围或本地范围声明的。 字符串文本也是静态对象。

一个自动对象,通常称为局部变量,它在函数或封闭范围内声明。

分配的对象是其内存由分配函数(如malloc(返回的对象。

实际上,编译器通常会将这些对象类型中的每一种放在不同的内存区域中。 静态对象通常放置在可执行文件的数据部分,自动(读取:本地(对象通常存储在堆栈上,分配的对象通常存储在上。

特别是字符串文本是静态对象,通常放置在标记为只读的数据部分的特殊部分中。

这些区域通常位于不同的内存区域中,但并非必须如此。 因此,虽然在实践中,每个区域中的对象地址会明显不同,但它们并不是必需的。

因此,您实际上不需要"确保"不同类型的变量位于不同的区域。 编译器会根据您定义它们的方式为您处理这个问题。

可能有助于获得为程序分配的实际部分的是 nm 命令,例如,您可以在那里看到static_store偏移量。

static_store: 30 at 0x600b00==>0000000000600b00 D static_store

在coliru上观看直播:http://coliru.stacked-crooked.com/a/1b45e01f508ec7b7

请注意附加的 nm 命令:gcc main.cpp && ./a.out && nm a.out

但是,您必须记住,您通常在具有 MMU 的系统上,因此虚拟内存地址映射到实际内存。

查找更多信息,例如 https://www.embeddedrelated.com/showarticle/900.php

我想尝试用更简单的方式解释这一点。

0x...是一个十六进制字符串,表示二进制位字符串。你可以把它想象成代表一个数字,但速记是因为你不需要知道这个数字,只是它与其他类似编码数字的相对值。所以这意味着"地址值"实际上只是一个数字。

为什么要用数字来表示内存位置?因为出于所有意图和目的,内存只是一个非常大的字节数组,其值可以通过索引读取。C 在逻辑上(不是物理上(将此内存阵列划分为不同的部分以实现高效存储。因此,内存中 2 个地址位置越接近,它们在该字节数组表示形式中的距离就越近。

任何应用程序可用的地址范围都是在运行时确定的,实际上不是特定内存空间的任何部分。因此,平心而论,没有理由确定某些项目位于某个内存区域中。只是在内存中靠近的 2 个对象位于不同的区域在统计上是非常不可信的。

最新更新