在函数、过程或者方法中定义一个字符串变量时,由于我们知道在函数、过程或者方法中定义的变量为局部变量,它的内存

是在栈中分配的,但是这里有个小细节我们要注意,对于一个局部的字符串变量,它的大小为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的内存分配(引)的更多相关文章

  1. delphi 精要-读书笔记(内存分配释放)

    delphi 精要-读书笔记(内存分配释放)     1.内存分为三个区域:全局变量区,栈区,堆区 全局变量区:专门存放全局变量 栈区:分配在栈上的变量可被栈管理器自动释放 堆区:堆上的变量内存必须人 ...

  2. 深度解析对象的hashcode和equals的差异,以及String的内存分配方式

    Q:Java对象的hashcode是怎么得到的 A:Java对象的hashcode是native方法,不是通过Java实现的.hashcode的值是根据对象的内存地址得到的一串数字. Q:如果两个对象 ...

  3. String的内存分配

    1.String类是final类不能被继承 2.String str="abc"的内部工作 (1)先在栈中定 一个名为str的String类的引用变量 String str: (2 ...

  4. JAVA基础-栈与堆,static、final修饰符、内部类和Java内存分配

    Java栈与堆 堆:顺序随意 栈:后进先出(Last-in/First-Out). Java的堆是一个运行时数据区,类的对象从中分配空间.这些对象通过new.newarray.anewarray和mu ...

  5. 标准C++类std::string的内存共享和Copy-On-Write...

    标准C++类std::string的 内存共享和Copy-On-Write技术 陈皓 1. 概念 Scott Meyers在<More Effective C++>中举了个例子,不知你是否 ...

  6. 【转】标准C++类std::string的内存共享和Copy-On-Write技术

    1.             概念 Scott Meyers在<More Effective C++>中举了个例子,不知你是否还记得?在你还在上学的时候,你的父母要你不要看电视,而去复习功 ...

  7. 标准C++类std::string的内存共享和Copy-On-Write技术

    标准C++类std::string的  内存共享和Copy-On-Write技术 陈皓 1. 概念 Scott Meyers在<More Effective C++>中举了个例子,不知你是 ...

  8. java内存分配和String类型的深度解析

    [尊重原创文章出自:http://my.oschina.net/xiaohui249/blog/170013] 摘要 从整体上介绍java内存的概念.构成以及分配机制,在此基础上深度解析java中的S ...

  9. 终于懂了:Delphi的函数名不是地址,取地址必须遵守Object Pascal的语法(Delphi和C的类比:指针、字符串、函数指针、内存分配等)good

    这点是与C语言不一样的地方,以前我一直都没有明白这一点,所以总是不明白:函数地址再取地址算怎么回事? ------------------------------------------------- ...

随机推荐

  1. 链表与哈希表基本概念及Java常用集合

    -链表- 是一种物理存储单元上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的.链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成.每个结点包括两个 ...

  2. 查询系统状态 内存大小 cpu信息 设备负载情况

    1.1 查看内存状态 /proc/meminfo里面存放着内存的信息 查看内存命令(包括虚拟内存swap): free -h (低版本系统可能不支持-h) 或者 free -m (以mb单位显示) a ...

  3. 多线程中的lock,Monitor.Wait和Monitor.Pulse

    我们知道lock实际上一个语法糖糖,C#编译器实际上把他展开为Monitor.Enter和Monitor.Exit,即: lock(lockObj) { //... } ////相当于(.Net4以前 ...

  4. 共享Session

    概述 现在的大型网站中,会面临实现多台服务器中的session数据共享问题.当使用多台服务器架设成集群之后,我们通过负载均衡的方式,同一个用户(或者ip)访问时被分配到不同的服务器上,假设在A服务器登 ...

  5. RabbitMQ及其.NET客户端——几个小例子

    一.简单生产者-消费者(使用direct交换器) 1.生产者 var factory = new ConnectionFactory();//实例化一个工厂 factory.HostName = &q ...

  6. 基于Geoserver发布时间地图

    Geoserver它是著名的开源GIS其中软件. 地图服务软件也经常使用的物品.基于geoserver和Openlayers它可以建立一个自由的,开放源码GIS工程. Geoserver公布地图的步骤 ...

  7. 1-5设定NetCore监听端口

    问题的起源:启动一个.netCore项目,默认使用的是5000端口,当我们有很多个项目的时候(集群),不可能都使用5000端口. 方法1:set ASPNETCORE_URLS=http://127. ...

  8. ATS项目更新(4) 更新DLL到远程服务器

    rem by jin tao rem upload dll to ta1bbn01 rem rem @echo off echo %time% set time1 = %,%%,%%,% rem ** ...

  9. Python多线程 简明例子

    综述   多线程是程序设计中的一个重要方面,尤其是在服务器Deamon程序方面.无论何种系统,线程调度的开销都比传统的进程要快得多. Python可以方便地支持多线程.可以快速创建线程.互斥锁.信号量 ...

  10. OpenGL(八) 显示列表

    OpenGL在即时模式(Immediate Mode)下绘图时,程序中每条语句产生的图形对象被直接送进绘图流水线,在显示终端立即绘制出来.当需要在程序中多次绘制同一个复杂的图像对象时,这种即时模式会消 ...