当数据尺寸在编译期不固定,而在运行期有可能要扩展到很大尺寸时,动态缓冲区在保存二进制数据方面显得非常有用。我们可以使用C++数组保存二进制数据,然后调用类似于memcpy的函数去动态的改变数组所占用空间的大小;我们还能够使用HBufC描述符,获取其可修改的描述符向其写入数据,然后调用ReAlloc方法扩展数组。以上两点方法可行,但是不好,因为我们得自己管理内存的分配。Symbian C++考虑到了这一点,于是引入了动态缓冲区的概念。
基于堆的缓冲描述符HBufC的前缀H显然不符合Symbian C++的命名规范(请参看Symbian编程总结-基础篇-类类型 )。在这里,“H”仅表明数据是存放在堆(Heap)上的 。虽然HBufC类以“C”为后缀,意思是不可修改的,但是我们可以通过HBufC::Des()方法获取其可修改的TPtr指针,对HBufC的内容进行修改。
一、堆描述符的构建
从TDesC类的栈内容构建
TDesC类有几个方法,允许将栈中的内容复制到堆中,并返回一个HBufC指针,这些方法的函数原型如下:
IMPORT_C HBufC16 * Alloc() const ;
IMPORT_C HBufC16 * AllocL() const ;
IMPORT_C HBufC16 * AllocLC() const ;
特别的,如果创建不成功,Alloc返回NULL,AllocL会抛出异常。
以下代码说明TDesC::Alloc的用法:
LOCAL_C void HBufCFromDesLC(HBufC *& aBuf)
{
_LIT(KText, " Hello World! " );
aBuf = KText().AllocLC();
}
LOCAL_C void MainL()
{
HBufC * buf;
HBufCFromDesLC(buf);
console -> Write(buf -> Des());
CleanupStack::PopAndDestroy(buf);
}
使用HBufC::New(L,LC)方法构建
通过HBufC::New(L,LC)方法创建时,需要在参数中指定所创建的内容占用堆空间的最大长度,如果接下来填充的数据长度超过了定义的长度则会抛出异常 :
IMPORT_C static HBufC16 * New(TInt aMaxLength);
IMPORT_C static HBufC16 * NewL(TInt aMaxLength);
IMPORT_C static HBufC16 * NewLC(TInt aMaxLength);
示例代码:
LOCAL_C void HBufCFromNewLC(HBufC *& aBuf)
{
aBuf = HBufC::NewLC( );
_LIT(KText, " Hello World My Girl! " );
TPtr ptr = aBuf -> Des();
ptr.Append(KText);
}
LOCAL_C void MainL()
{
HBufC * buf;
HBufCFromNewLC(buf);
console -> Write(buf -> Des());
CleanupStack::PopAndDestroy(buf);
}
按照字面理解,以上代码第3行申请了最大长度为19的堆内存,而字符串“Hello World My Girl!”的长度为20,程序能正常运行且没有抛出异常。为什么呢?SDK是这样解释的:
therefore, the resulting maximum length of the descriptor may be larger than requested.
HBufC预留的空间会比我们申请的空间大一些,如果我们将第三行代码换成aBuf = HBufC::NewLC(18);应用程序就会抛出异常。
使用HBufC::NewMax(L,LC)方法创建
HBufC::NewMax方法与HBufC::New方法类似,唯一不同的是,在使用New方法构建HBufC时,HBufC的Length为0,而使用NewMax方法,HBufC的Length会置为MaxLength。
示例代码如下:
LOCAL_C void HBufCFromNewMaxLC(HBufC *& aBuf)
{
aBuf = HBufC::NewMaxLC( );
_LIT(KText, " Hello World My Girl! " );
TPtr ptr = aBuf -> Des();
ptr.Copy(KText);
}
LOCAL_C void MainL()
{
HBufC * buf;
HBufCFromNewMaxLC(buf);
console -> Write(buf -> Des());
CleanupStack::PopAndDestroy(buf);
}
注意此处第7行使用的是Copy方法而不是Append方法。因为NewMax方法已经将Length设为19,如果再使用Append方法会使插入的数据超过最大缓冲区长度,从而抛出异常。
二、 堆描述符的内容扩展
当为HBufC所分配的现有内存不够用时,需要扩展HBufC的内容,我们可以使用ReAlloc函数对HBufC占用的堆空间进行扩展。ReAlloc方法将进行以下三个步骤:
1. 在内存中创建一个新的基于堆描述符
2. 将旧的堆描述符的内容复制到新的堆描述符
3. 删除旧的堆描述符
从以上3点我们可以了解到,HBufC::ReAlloc方法会在堆中开辟另外一块内存空间,指向原来HBufC空间的指针将会被删除 。所以,为了保证程序能正确运行,我们在调用ReAlloc的时候,不要忘记调用以下方法:
1. 如果堆描述符被加入了清理栈,将堆描述符从堆中弹出
2. 如果在ReAlloc之前使用Des方法获取了指向堆数据的指针描述符,在ReAlloc调用之后得重新获取
以下是示例代码:
LOCAL_C void HBufCReAllocLC(HBufC *& aBuf)
{
aBuf = HBufC::NewLC( );
_LIT(KText, " Hello World My Girl! " );
_LIT(KNewLine, " \n " ); TPtr ptr(aBuf -> Des());
ptr.Copy(KText);
CleanupStack::Pop(aBuf);
aBuf = aBuf -> ReAlloc( 60 );
CleanupStack::PushL(aBuf);
ptr.Set(aBuf -> Des());
ptr.Append(KNewLine);
ptr.Append(KText);
}
LOCAL_C void MainL()
{
HBufC * buf;
HBufCReAllocLC(buf);
console -> Write(buf -> Des());
CleanupStack::PopAndDestroy(buf);
}
另:第16行我们使用的是TPtr::Set方法而不是TPre::operator =()赋值方法,原因是:Set()将不仅将描述符指向新的数据区域,还将描述符的长度和最大长度两个成员变量修改了。而operator =()会将数据复制过来,但是长度和最大长度这两个成员变量不会改变。
所以在第16行如果我们只是简单的使用ptr = aBuf->Des();,ptr的长度和最大长度没有改变,都只是在调用ReAlloc之前的20,当执行到17行时,所添加的文字内容超过了描述符的最大长度,在此处会抛出异常。
三、小结
我们在这一节里简单的回顾了堆描述符HBufC。HBufC也可以作为动态缓冲区来运用,但其不够灵活,在HBufC::ReAlloc调用以后,我们得重新将指向其的指针定位。在下一节里,我们将学习Symbian C++为我们封装的动态缓冲区类CBufFlat、CBufSeg和RBuf类。这几个类将为我们解决以上问题。
四、参考文献
1. Symbian OS C++ 高效编程
转自:http://www.cnblogs.com/felixYeou/archive/2008/12/01/1344880.html
分享到:
相关推荐
在Symbian C++手机编程...这些特性使得Symbian C++的字符串处理更加高效且安全,尤其是在处理大量字符串操作时,避免了C风格字符串带来的缓冲区溢出等安全隐患。了解和熟练使用这些机制对于Symbian平台的开发至关重要。
在Symbian操作系统上进行C++编程是一项技术性极强的工作,它涉及到一系列特定的规则和最佳实践。以下是一些关键的Symbian C++编程注意事项,这些知识点将帮助开发者编写出高效、稳定且安全的代码。 1. **内存管理**...
在Symbian操作系统中,动态数组和缓冲区的管理是至关重要的,特别是在嵌入式开发领域,高效且安全的数据结构是程序性能的关键因素。这里主要介绍Symbian系统中的RArray、RPointerArray以及CArrayX系列类,它们都是...
576.2 一般描述符方法 586.3 使用HBufC堆描述符 616.4 外部化和内部化描述符 626.5 TFileName的过度使用 646.6 在描述符操纵方面有用的类 646.7 小结 66第7章 动态数组与缓冲区 687.1 CArrayX类 697...
除了TBuf之外,SymbianOS还提供了一种动态分配的描述符——HBufC,它是在堆上分配的内存块。HBufC的主要特点是可以动态调整大小,非常适合于处理不确定长度的字符串或其他数据。 1. **创建HBufC**: ```cpp HBufC...
总结来说,理解Symbian的基础知识对于开发Symbian应用程序至关重要。掌握基本数据类型、描述符的使用、错误处理机制以及特定的命名规则,能帮助开发者更好地融入Symbian的开发环境,编写高效且可靠的代码。
相较于传统的 C++ 编程环境,Symbian 在字符串处理方面引入了一系列独特的概念和技术,旨在满足移动设备对内存管理的特殊需求。本文将深入探讨 Symbian 平台上字符串处理的关键知识点,特别是针对 TPtr 和 TPtrC 的...
根据给定的信息,本文将详细解释Symbian操作系统中如何实现动态加载汉字的过程,并通过具体的代码片段进行解析。 ### Symbian系统中的汉字处理 Symbian系统是一款为移动设备设计的操作系统,广泛应用于智能手机和...
Symbian的字符串类主要包括TDes和HBufc,它们都是基于内存缓冲区的。TDes是“动态可扩展字符串”的缩写,它是一个可以动态增长或缩小的缓冲区,用于存储字符串。HBufc则是一个分配在heap上的缓冲区,用于创建和管理...
### Symbian C++编程基础知识点详述 #### 移动应用开发:Symbian C++编程基础概览 在移动应用开发领域,Symbian操作系统曾是智能手机平台的领头羊之一,尤其是在2000年代初期至中期。Symbian C++是一种专门为...
以下是对标题“Symbian程序的部分要点总结”中提到的关键知识点的详细解释: 1. **C类与析构函数**:所有继承自`CBase`的类必须提供一个析构函数,因为`CBase`中的析构函数是虚函数。析构函数用于清理对象在生命...
`HBufC`是Symbian系统中用于处理字符串缓冲区的一个类。在使用`HBufC`时需要注意: - 在删除`HBufC`变量后将其设置为`NULL`,以防析构函数试图删除一个已不存在的`HBufC`对象。 - 不需要使用`HBufC::Des()`来获取`...
- **堆描述符(Heap)**:HBufC将数据存储在堆上,大小在运行时动态决定。 - **指针描述符(Pointer)**:TPtr和TPtrC用于引用类外部的数据,可以是可修改的或不可修改的。 2. **描述符修改** - **可修改...
《Symbian操作系统基础知识——通过Lab_04303.cb1学习Symbian基本数据类型》 在移动操作系统的历史中,Symbian系统曾占据过重要的地位,尤其是在功能手机时代,它以其强大的功能和良好的可扩展性吸引了众多开发者。...
- **知识点**: 在Symbian OS开发中,CCBase类是一个非常重要的基础类,它为所有用户自定义类提供了基本的功能支持,特别是内存管理和异常处理方面。 - **详细解释**: CCBase类提供了一些关键的方法来帮助开发者进行...
本篇文章将深入探讨Symbian系统中的常见功能实现,包括全屏显示、开机自启动等关键点,旨在帮助开发者更好地理解和应用Symbian系统。 1. **全屏显示**: 全屏显示是Symbian应用程序中常见的需求,通过调整窗口管理...
### Symbian中显示中文汉字(3种方法) 在Symbian操作系统中处理中文显示是一项基本但又重要的功能。本文将详细介绍三种不同的方法来实现这一功能,并解释每种方法的具体步骤和技术要点。 #### 方法一:使用UTF-8...
在Symbian中,TPtrC、TBufC、HBufC是TDesC的派生类型,而TPtr和TBuf则是从TDes派生,它们提供了常量操作的便利。TDesC和TDes是抽象类,而_LIT则用于创建静态文本,这些基础知识对于深入学习Symbian开发至关重要。 ...
在Symbian操作系统中,描述符(Descriptors)是用于高效管理字符串的重要机制。字符串在Symbian中被称为Descriptor,它们可以存在于RAM或ROM中,因此系统提供了多种类型的字符串类以适应不同的需求和内存管理策略。 ...
在Symbian C++编程中,我们通常会创建一个继承自CListBox的子类,并重写一些关键方法来实现自定义行为。 1. **创建ListBox**:在Symbian中,创建ListBox涉及在资源文件中定义控件,并在构造函数中实例化它。资源...