DELPHI之关于String的内存分配(引)
在函数、过程或者方法中定义一个字符串变量时,由于我们知道在函数、过程或者方法中定义的变量为局部变量,它的内存
是在栈中分配的,但是这里有个小细节我们要注意,对于一个局部的字符串变量,它的大小为4字节,这个在栈中分配的4字
节是不是就是字符串变量的全部呢?答案是否定的,它在栈中保存的只是这个字符变量的大小和字符变量的值在堆中的内存
地址!,这就是说,该字符变量的值并不在对应的栈中,而是在堆中!我们了解到在堆上分配的内存是要程序员来处理内存
释放的,而我们在使用String类型的变量时从来就没有处理过该变量占用的内存!这是什么原因呢?这里我们就要讲到
编译器的引用计数原理了,正是因为它为我们省去了很多麻烦(当然,在某些情况我们还是小心为上,下面会提出),引用
计数其实通俗的讲就是这块内存被几个变量引用,就为这块内存计上数(可能表述不正确,但为了好记好理解故此说),是
1个就是1,有2个就是2,以此类推。当一个字符串变量使用完后,编译器自动的将其引用计数减1,如果发现引用计数为0
时,这个字符变量所占用的内存空间就被释放了。需要注意的是,什么情况下会发生引用计数呢?如果定义一个字符串变量
并给其赋值,那么这个字符串变量引用计数为1,此时假若我们再定义一个字符串变量,并将第一个字符变量的值赋值给第
二个字符变量,此时将引发引用计数,变为2,注意,编辑器此时并没有给第二个字符变量复制一份第一个字符变量的值,
而只是将第一个字符变量值的地址指针给了它!也就是说,第一个和第二个字符的值都在同一个内存块中!。但是我们通过
访问数组元素的方式访问字符变量的时候或者修改上面其中一个字符变量时,这时会引发”写复制“,之后两个字符串变量开
始使用不同的内存占用。因为所有这些对程序员来说是不必费心处理的,它全部由编译器来自动完成,那么我们在什么情况
下要小心呢?这里就和DLL有关系了,我们知道在EXE程序调用DLL时,EXE和DLL之间都是各自使用自己的内存管理器,
麻烦就出在这,假如我们在EXE中调用DLL的一个输入函数时返回一个字符串,我们知道这个字符串的引用计数为1,EXE在
使用完这个字符串后将其引用计数减1,那就是0了,按照惯例,编译器对字符串所占用的内存进行清除释放,OK,一切顺利,
那么这时该轮到DLL处理了,前面说过EXE和DLL各有各的内存管理器,这时DLL是不知道EXE已将字符串内存释放掉了,并
且还要访问那个被释放了的字符串,字符串都不存在了,访问哪儿呢?于是程序就出问题了,很显然这是我们所不希望看到的,
所在在使用DLL时,为了避免这个问题发生,我们可以有多种解决方案
1、使用内存映射文件
2、DLL单元和EXE单元都引用ShareMem单元
3、不用String类型(注:动态数组、接口和变体类型也有引用计数机制),改用PChar类型
https://i.cnblogs.com/EditPosts.aspx?opt=1
DELPHI之关于String的内存分配(引)的更多相关文章
- delphi 精要-读书笔记(内存分配释放)
delphi 精要-读书笔记(内存分配释放) 1.内存分为三个区域:全局变量区,栈区,堆区 全局变量区:专门存放全局变量 栈区:分配在栈上的变量可被栈管理器自动释放 堆区:堆上的变量内存必须人 ...
- 深度解析对象的hashcode和equals的差异,以及String的内存分配方式
Q:Java对象的hashcode是怎么得到的 A:Java对象的hashcode是native方法,不是通过Java实现的.hashcode的值是根据对象的内存地址得到的一串数字. Q:如果两个对象 ...
- String的内存分配
1.String类是final类不能被继承 2.String str="abc"的内部工作 (1)先在栈中定 一个名为str的String类的引用变量 String str: (2 ...
- JAVA基础-栈与堆,static、final修饰符、内部类和Java内存分配
Java栈与堆 堆:顺序随意 栈:后进先出(Last-in/First-Out). Java的堆是一个运行时数据区,类的对象从中分配空间.这些对象通过new.newarray.anewarray和mu ...
- 标准C++类std::string的内存共享和Copy-On-Write...
标准C++类std::string的 内存共享和Copy-On-Write技术 陈皓 1. 概念 Scott Meyers在<More Effective C++>中举了个例子,不知你是否 ...
- 【转】标准C++类std::string的内存共享和Copy-On-Write技术
1. 概念 Scott Meyers在<More Effective C++>中举了个例子,不知你是否还记得?在你还在上学的时候,你的父母要你不要看电视,而去复习功 ...
- 标准C++类std::string的内存共享和Copy-On-Write技术
标准C++类std::string的 内存共享和Copy-On-Write技术 陈皓 1. 概念 Scott Meyers在<More Effective C++>中举了个例子,不知你是 ...
- java内存分配和String类型的深度解析
[尊重原创文章出自:http://my.oschina.net/xiaohui249/blog/170013] 摘要 从整体上介绍java内存的概念.构成以及分配机制,在此基础上深度解析java中的S ...
- 终于懂了:Delphi的函数名不是地址,取地址必须遵守Object Pascal的语法(Delphi和C的类比:指针、字符串、函数指针、内存分配等)good
这点是与C语言不一样的地方,以前我一直都没有明白这一点,所以总是不明白:函数地址再取地址算怎么回事? ------------------------------------------------- ...
随机推荐
- 【BZOJ 1012】 [JSOI2008]最大数maxnumber(线段树做法)
[题目链接]:http://www.lydsy.com/JudgeOnline/problem.php?id=1012 [题意] [题解] 预开一个20W长度的线段树; 这里a[1..20W]={0} ...
- python request get
import requests from urllib import parse # 返回response resp = requests.get("https://www.baidu.co ...
- TCP可靠的传输机制
TCP提供一种面向连接的.可靠的字节流服务.面向连接意味着两个使用TCP的应用(一般是一个客户和一个server)在彼此交换数据包之前必须先建立一个TCP连接.这一过程与打电话非常相似.先拨号振铃,等 ...
- spring boot jar 部署linux服务器
用命令启动spring boot 项目,一旦终端命令窗口关闭,项目也就关闭了,所以我们采用脚本的方式来运行jar 正常命令 java -jar xxx.jar 脚本启动,vim 创建 start.sh ...
- 高并发场景之RabbitMQ
高并发场景之RabbitMQ 上次我们介绍了在单机.集群下高并发场景可以选择的一些方案,传送门:高并发场景之一般解决方案 但是也发现了一些问题,比如集群下使用ConcurrentQueue或加锁都不能 ...
- PCI GXL学习之再造篇
作者:朱金灿 来源:http://blog.csdn.net/clever101 再造一个PCI GXL?听起来是一件颇有难度的事,实际上并非不可能.本文拟从必要性.可行性和技术路线等方面谈谈再造PC ...
- layer的使用笔记
$('#calendar').fullCalendar({ lang:"zh-cn", buttonText:{ today: '今天' }, eventLimit: true, ...
- SQLyog 报错2058 :连接 mysql 8.0.12 解决方法
今天闲来无事,下载新版的 mysql 8.0.12 安装. 为了方便安装查看,我下载了sqlyog 工具 连接 mysql 配置新连接报错:错误号码 2058,分析是 mysql 密码加密方法变了. ...
- shell问题集合
1.syntax error near unexpected token `then' if后要有空格,[] 中括号的开头和结尾要有空格! [ $1-eq"root" ]中括号中的 ...
- 怎么会float交换器int
最近突然想知道编译器整数浮球开关是如何实现的,现在很多信息,但遗憾的是甚至没有这方面的记录,所以我决定实现自己的简单的整数浮点转 随着float开启int为例 double转int类似 在做强转之前 ...