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语言不一样的地方,以前我一直都没有明白这一点,所以总是不明白:函数地址再取地址算怎么回事? ------------------------------------------------- ...
随机推荐
- 【poj3690】Constellations 哈希
传送门 题目分析 考虑将大矩阵的每个1*q矩阵哈希值求出,然后让小矩阵的第一行在大矩阵中找,如果找到,并且能匹配所有行则出现过.否则没出现过. 在初始化1*q矩阵时可以进行优化:假设该行为123456 ...
- scala 中的修饰符
package cn.scala_base.oop.scalaclass import scala.beans.BeanProperty; /** * scala中的field,类中定义的是方法,函数 ...
- Compile Graphics Magick, Boost, Botan and QT with MinGW64 under Windows 7 64
Compile Graphics Magick, Boost, Botan and QT with MinGW64 under Windows 7 64 Sun, 01/01/2012 - 15:43 ...
- 辨异 —— 行星 vs 恒星
star:恒星,planet:行星: 1. 恒星 恒星是指宇宙中靠核聚变产生的能量而自身能发热发光的星体(比如太阳).过去天文学家以为恒星的位置是永恒不变的,以此为名.但事实上,恒星也会按照一定的轨迹 ...
- WPF 触摸到事件
原文:WPF 触摸到事件 本文从代码底层告诉大家,在触摸屏幕之后是如何拿到触摸点并且转换为事件 在 WPF 界面框架核心就是交互和渲染,触摸是交互的一部分.在 WPF 是需要使用多个线程来做触摸和渲染 ...
- win10 支持默认把触摸提升鼠标事件 打开 Pointer 消息
原文:win10 支持默认把触摸提升鼠标事件 打开 Pointer 消息 在 WPF 经常需要重写一套触摸事件,没有UWP的Pointer那么好用. 如果一直都觉得 WPF 的触摸做的不好,或想解决 ...
- asp.net中C#调用存储过程
创建存储过程: create procedure houseCount ( ), @house_count int output ) as select @house_count=COUNT(*) f ...
- docker入门1: Dockerfile介绍
Dockerfile是为快速构建docker image而设计的,当你使用dockerbuild 命令的时候,docker 会读取当前目录下的命名为Dockerfile(首字母大写)的纯文本文件并执行 ...
- 至Linux-2.6.32编译内核ipset-6.23坎坷的经历
新的版本号ipset 上周,一名医生在儿童医院等待一段差距叫做数量.接受NetfilterPush信息的邮件列表,列表ipset最新6.23版本号的新功能,非常喜欢我现在需要的是,特别是timeout ...
- 解决:insert Vodafone sim card,open the mms read report,when receive the read report,cann't download..
insert Vodafone sim card,open the mms read report,when receive the read report,cann't download the m ...