关于字符串String内存管理

获得String 类代码

以前是用Reflector现在可以通过Visual Studio 2008的源代码调试的方式获得String类的源代码。具体方法可以参考横刀天笑 的文章。要Load System.dll 的符号表文件,然后再将调试断点设定在一行字符串操作代码上,最后按F11键,就可以看到全部的String 类代码了

 

“字符串是不可变的”以及字符串内存管理

这句话有点儿难理解。其实是指字符串占用的空间,字符串的内存控件,一旦申请了,就没法随意的伸缩了。如果需要修改字符串内容的大小,比如添加几个字符,就需要重新向内存申请空间。在字符串使用者看来,这没什么。但是对于计算机和OS的内存管理来说,就是一个比较大的挑战。下面列举一种情况:假设你有一篇小诗要放入内存,大概占用了318个字节。你还有一篇文章要保存,占用了内存5K的空间。




此时,如果将318个字节释放掉,然后要放入一个800字节的字符串。那么对于内存管理来说可能就是一个噩梦。因为虽然6K的内存有1K的剩余空间,但是地址并不连续。其实,有足够的空间并不意味着就可以存放对象,还要看存放对象的空间内存地址是不是连续的。当然,对于上述情况,绝大多数情况下OS的内存管理是不会弹出一个“Out of memory”了事儿的。OS内存管理模块会依据算法将某些内存页调出,保存到磁盘,再修改内存映射表…… 总之,会让计算机忙上一阵子。

如果我们在堆内存中频繁的申请、释放一个或者几个字节,那么要不了多久,在可用内存总数不变的情况下,内存空间就会“千疮百孔”也就是我们常说的内存碎片。好在.NET CLR 的GC可以对内存碎片进行整理,但这也是一个非常耗时的工作。

那么对于这么头疼的问题有什么好办法么一种解决办法是,给内存设定阀值,比如,设定最小内存申请空间为:512个字节。当申请318个字符的存储空间时,OS实际上分配了512个字节。这样保证内存的申请和释放都是一些相对“完整”的内存“块”以减少内存碎片的产生。还有一种办法就是尽量遵循“不可变”的原则,减少字符串在创建后的伸长和缩短的操作。

说了这么多,只是让看客们了解一些基础知识,以便更好的理解string类的代码。言归正传……


String 类概述

String 类源代码一共有3257行。作为容器(容纳字符的容器),String 类继承了IComparable、ICloneable、IConvertible、IEnumerable 接口,以便调用者枚举、拷贝、转换容器中的字符。在声明中还有下面的代码:
#if GENERICS_WORK
, IComparable, IEnumerable, IEquatable
#endif

这表示源代码的编写者考虑到了对泛型的支持。如果使用C# 2.0 标准的编译器编译代码,那么String 类还需要继承这三个泛型接口。String 类的方法约有80个(不包括重载形式)。我大概给他们分了分类:
1) 内存申请函数,FastAllocateString。
2) 构造函数,提供了8种构造的重载形式用来构建字符串对象。
3) 字符串操作函数,例如Insert、Join、Substring等,可以对字符串的内容进行修改。
4) 字符串特征函数,例如IsNullOrEmpty、IsNormalize等,向调用者返回当前字符串内容的特征。
5) 格式化字符串函数,Format。
6) 接口实现函数,如String.Iconvertible.ToBoolean() 等。
7) 内部辅助函数。

内存申请函数

FastAllocateString(int iLength) 这个函数不在String.cs中实现,其声明为:
private extern static String FastAllocateString(int length); 具体实现不详(为此苦恼了很久……)。但从该函数的声明可以看出,该函数可以在托管堆上申请一片指定长度的内存,并返回一个String类型的引用地址。在String类中,凡是需要申请内存的地方,都是使用这个函数。

构造函数

在8种构造函数中,最基本的构造函数的声明:
[CLSCompliant(false), MethodImplAttribute(MethodImplOptions.InternalCall)]
unsafe public extern String(sbyte *value, int startIndex, int length, Encoding enc);

也就是说,要给定一个指向字符串首地址的指针(sbyte *value),要创建的字符串在给定的字符串中的起始索引位置(int startIndex),字符串长度(int length),以及编码对象(Encoding enc)。
其实,不论那种构造,最终都是调用CreateString静态函数创建的字符串对象。

来自:http://www.tzwhx.com/newOperate/html/1/12/123/12028.html

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值