Delphi 之 内存篇(二)

  系统给程序的地址数是 4G, 为什么不是 3G 或 5G? 因为 32 位的指针的最大值就是 $FFFFFFFF, 它不能表示更多了, 究其根源这要回到 CPU 的寻址能力、地址总线等等.

在 Win64 下, 系统给程序的地址数达到了 16EB(0 - $FFFFFFFFFFFFFFFF), 也就是
18446744073709551616 个. 不过 Win64 还没有普及, 我们还得回到实际的 Win32.

就这 4G 的地址,
系统还要留下一半($80000000 - $FFFFFFFF, 这 2G 是各进程共享的)用作宏观管理; 只给程序 2G(0 -
$7FFFFFFF).
就这 2G 的地址, 也不是全给用户的, 低端的 0 - $FFFF 是用于空指针分配, 禁止访问; 高端的 $7FFF0000
- $7FFFFFFF 也留出来作为进程的临界区, 也禁止访问. 其实进程的私有空间地址只有 $10000 - $7FEFFFF.

上面这个结果,
我们可以通过 GetSystemInfo 函数得到证实, 通过 GetSystemInfo 函数能获取一个 TSystemInfo 结构, 结构中的
lpMinimumApplicationAddress 和 lpMaximumApplicationAddress
分别表示程序(或动态链接库)可以访问的最低与最高的内存地址.

var
  si: TSystemInfo;
begin
  GetSystemInfo(si);
  ShowMessageFmt(‘%p-%p‘, [si.lpMinimumApplicationAddress, si.lpMaximumApplicationAddress]);
  {结果是: 00010000-7FFEFFFF}
end;

通过 GetSystemInfo 还能得到一个内存相关的重要参数: 页大小(PageSize)

var
  si: TSystemInfo;
begin
  GetSystemInfo(si);
  ShowMessage(IntToStr(si.dwPageSize)); {4096; 4096 字节也就是 4K}
end;

PageSize 是系统管理内存的基本单位, 之所以需要用 GetSystemInfo 获取不同系统的 PageSize 也会有区别.

我们需要知道的是, 用 VirtualAlloc 函数分配的内存就是以 PageSize(4K) 为最小单位的; 假如我们用
VirtualAlloc 给一个整数(4个字节)分配内存, 将会浪费 4092 个字节, 也就是说 VirtualAlloc 不适合分配小内存,
因而也有了多种分配内存的函数.

暂时放下这个话题, 先了解一下 "栈".

说到 "栈", 就想到 "堆", 还有 "堆栈" 指的也是 "栈"; "栈" 与 "堆"
都是程序可操作的内存区域($10000 - $FFEFFFF)中的某一小段.

系统函数中有 HeapReAlloc、GlobalAlloc 等分配
"堆" 的函数, 却没有分配 "栈" 的函数, 这是因为 "栈" 是程序自动管理的; 每个程序都从自己的可用地址范围内留出一块作为 "栈",
程序根据需要可以自动调节它的大小, 但咱们可以设置它的最大值与最小值. 在Delphi 中可以从这里设置:
Project -> Options
-> Linker -> [Min stack size 和 Max stack size]

"栈" 用来暂存局部变量和函数参数,
由程序在需要时申请, 用完就释放.

因为 "栈" 的空间一般不是很大, 所以咱们一般不要把局部变量弄得太大(特别是在使用数组的时候);

因为访问 "栈" 比访问 "堆" 来的简洁, 速度快, 所以要尽量多用局部变量、少用全局变量.

时间: 2024-08-01 06:09:12

Delphi 之 内存篇(二)的相关文章

Oracle内存管理理论篇二

目标 了解oracle内存管理方式 掌握ASMM管理方式 掌握AMM管理方式 监控内存使用 学习一个知识点时,最好先了解其历史.ORACLE近期的版本都对内存管理做了简化,从9i通过PGA_AGGREGATE_TARGET参数实现PGA的自动管理,10g通过Automatic Shared Memory Management(ASMM)实现SGA的自动管理,到11g通过Automatic Memory Management(AMM)实现内存(SGA+PGA)的自动管理.目前的11G版本,DBA只

SQL Server调优系列玩转篇二(如何利用汇聚联合提示(Hint)引导语句运行)

原文:SQL Server调优系列玩转篇二(如何利用汇聚联合提示(Hint)引导语句运行) 前言 上一篇我们分析了查询Hint的用法,作为调优系列的最后一个玩转模块的第一篇.有兴趣的可以点击查看:SQL Server调优系列玩转篇(如何利用查询提示(Hint)引导语句运行) 本篇继续玩转模块的内容,同样,还是希望扎实掌握前面一系列的内容,才进入本模块的内容分析. 闲言少叙,进入本篇的内容. 技术准备 数据库版本为SQL Server2012,利用微软的以前的案例库(Northwind)进行分析,

SQL Server调优系列基础篇(并行运算总结篇二)

原文:SQL Server调优系列基础篇(并行运算总结篇二) 前言 上一篇文章我们介绍了查看查询计划的并行运行方式. 本篇我们接着分析SQL Server的并行运算. 闲言少叙,直接进入本篇的正题. 技术准备 同前几篇一样,基于SQL Server2008R2版本,利用微软的一个更简洁的案例库(Northwind)进行解析. 内容 文章开始前,我们先来回顾上一篇中介绍的并行运算,来看文章最后介绍的并行运算语句: SELECT B1.[KEY],B1.DATA,B2.DATA FROM BigTa

线程篇(二)

C# 温故而知新: 线程篇(二) 线程池和异步线程 目录: 1 什么是CLR线程池? 2 简单介绍下线程池各个优点的实现细节 3 线程池ThreadPool的常用方法介绍 4 简单理解下异步线程 5 异步线程的工作过程和几个重要的元素 6 有必要简单介绍下Classic Async Pattern 和Event-based Async Pattern 7 异步线程的发展趋势以及.net4.5异步的简化 8 本章示例 自定义一个简单的线程池 Asp.net异步IHttpAsyncHandler示例

Android 终端性能测试——内存篇

前言 做Android QQ性能测试时,内存测试中遇到不少困惑,"各种"内存术语,到底什么意思,怎么获取,这里总结一下. 进行的内存测试主要有两个方面,一,OOM的发现和定位,二,同历史版本或竞品的对比测试.关于oom可以用MAT进行分析,具体分析方法参见susanwu在km上的文章<如何使用Memory_Analyzer分析内存泄漏>.下面主要总结一下Android性能测试中常用的方法及解释 一:running services"查看service进程内存 从A

【转贴】内存系列二:深入理解硬件原理

内存系列二:深入理解硬件原理 https://www.cnblogs.com/tcicy/p/10087457.html 忘记转这一篇了 内存相关的东西 其实理解了挺好的.. cache还有main memory 本篇文章承接上文继续介绍DDR内存的硬件原理,包括如何寻址,时序和时延以及可以为提高内存的效能可以有哪些方法. 上次虽然解决了小张的问题,却引发了他对内存原理的兴趣.这不他又来找我了,说我还欠他一个解释.这次我们约在一个咖啡馆见面,这次内容有点深入,我带了些图片,小张也点了一大杯美式,

【转】java提高篇(二)-----理解java的三大特性之继承

[转]java提高篇(二)-----理解java的三大特性之继承 原文地址:http://www.cnblogs.com/chenssy/p/3354884.html 在<Think in java>中有这样一句话:复用代码是Java众多引人注目的功能之一.但要想成为极具革命性的语言,仅仅能够复制代码并对加以改变是不够的,它还必须能够做更多的事情.在这句话中最引人注目的是"复用代码",尽可能的复用代码使我们程序员一直在追求的,现在我来介绍一种复用代码的方式,也是java三大

JMS基础篇(二)

简介 异构集成是消息发挥作用的一个领域,大型公司内部可能会遇到很多的平台,Java,.net或者公司自己的平台等. 传送消息还应该支持异步机制,以提高系统整体的性能.异步传输一条消息意味着,发送者不必等到接收者接收或者处理消息,可以接着做后续的处理. 应用程序发送消息至另外一个应用程序,需要使用到消息中间件.消息中间件应提供容错,负载均衡,可伸缩的事务性等特性. JMS与JDBC类似,是一种与厂商无关的API.应用程序开发者可以使用同样的API来访问不同的系统. 可以认为JMS是一种标准,各消息

Linux环境编程之共享内存区(二):Posix共享内存区

现在将共享内存区的概念扩展到将无亲缘关系进程间共享的内存区包括在内.Posix提供了两种在无亲缘关系进程间共享内存区的方法: 1.内存映射文件:由open函数打开,由mmap函数把得到的描述符映射到当前进程地址空间中的一个文件.(上一节就是这种技术) 2.共享内存区对象:由shm_open打开一个Posix名字(也许是在文件系统中的一个路径名),所返回的描述符由mmap函数映射到当前进程的地址空间.(本节内容) Posix共享内存区涉及以下两个步骤要求: 1.指定一个名字参数调用shm_open