在 c 或 c++ 程序中可以在三个区域创建变量。
- 全局或静态变量位于可执行二进制文件中的固定位置。
- 静态范围之外的自动变量在堆栈中
- malloc'ed 或 calloc'ed 变量在堆上。
free() 是释放堆上先前分配的内存的函数。 malloc 或类似函数返回指向堆上内存的指针。读取或写入该内存的唯一方法是通过指针。指针是地址,指针* 是指向该地址的内容。
在显示的示例中,有两个变量,定义在 Main 中,实际上是静态的,以及来自 Main 的返回值,它在堆栈上。使用最小整数,16 位,这是一个可能的内存映射。在此映射中,指令从 0 开始,堆栈从某个非零值(堆栈的开头 - bos)开始并通过递增而增长,并且堆从最大地址(...FFFF,又名 -1)开始并通过递减而增长:
(记住,MIN_INT 是 -32768,MAX_INT 是 32767...规范只保证 16 位,有符号)
每个字节都有一个“n”位宽的地址 - 通常为 16、32 或 64 位
-1。 (堆开始,例如16位地址:0xFFFF,32位地址:0xFFFFFFFF或64位地址:0xFFFFFFFFFFFFFFFF)
-2。 (从堆开始向下的第一个位置。0x...FFFE)ptr[9],一次
-3。 (从堆开始向下的第二个位置。0x...FFFD)
-4。 (从堆开始向下的第三个位置。0x...FFFC)ptr[8],一次
[剪辑]
-17。 (从堆开始向下的第 16 个位置。0x...FFEF)
-18。 (从堆开始向下的第 17 个位置。0x...FFEE)ptr[1],一次
-19。 (从堆开始向下的第 18 个位置。0x...FFED)
-20(从堆开始向下的第 19 个位置。0x...FFEC)ptr[0],一次
-21。 (堆顶,从堆开始向下 10 X 16 位整数。0x...FFEB),一次
:
32 位或 64 位机器上的地址范围非常大...
:
tos: (栈顶 0x...tos)
bos + ( sizeof( int ) - 1) 从 Main() 返回的 int 结束
bos:(栈的开始:在静态数据之上)从Mail()返回的int的开始
togs:(全局/静态顶部)“ptr”结束
:(指针的大小是地址总线的宽度......不管它需要什么)
togs-(n-1): (top of global/static - (sizeof( int* ) - 1)) “ptr”开始
(togs-n) : “ret”结束
(togs-n)-1: "ret" 的开始
(编译器为自己、调试器等添加的任何全局内容)
(程序代码结束)
(程序代码的开始)
(非程序代码的顶部)
0(非程序代码开始,0x...0000)
在运行时,“ptr”和“ret”可能都从“0”开始,因为它们是固定的、静态的值,从可执行二进制文件来源的文件中读出。
随着程序的运行,“ptr”的值发生变化,首先,指向堆,在 malloc 的 10 个整数数组:“0x...FFEC”
对 free() 的调用不会改变 ptr 的值,它仍然是“0x...FFEC”
释放“0x...FFEC”是合法的,并且运行起来没有任何有趣的东西。
赋值“ptr = &ret”将新值设置为“ptr”,“(togs-n)-1”,“ret”的开始。
释放“(togs-n)-1”会导致立即崩溃,因为“free”会检查“(togs-n)-1”的值,并且它不在堆地址的有效范围内。
"ret" 保持空白,从未设置,但由于它是全局/静态的,它保持在链接器将其写入磁盘时的任何状态。