RBuf construction and usage

While there is a non-modifiable heap descriptor class, HBufC, there is no corresponding modifiable HBuf class, which might have been expected in order to make heap buffers symmetrical with TBuf stack buffers. However, since Symbian OS v8.1, the RBuf class has been available for use as a modifiable heap-based buffer class.

RBuf objects can be instantiated using Create(), CreateMax() or CreateL() to specify the maximum length of descriptor data that can be stored. It's also possible to instantiate an RBuf and copy the contents of another descriptor into it, as follows:

RBuf myRBuf;

_LIT(KHelloRBuf, "Hello RBuf!"); myRBuf.Create(KHelloRBuf());

Create() allocates a buffer for the RBuf to reference. If that RBuf previously owned a buffer, Create() will not clean it up before assigning the new buffer reference, so this must be done explicitly by calling Close() first to free any pre-existing owned allocated memory.

Alternatively, an RBuf can be instantiated to take ownership of a pre-existing section of memory using the Assign() method.

// Taking ownership of HBufC HBufC* myHBufC = HBufC::NewL(20); RBuf myRBuf.Assign(myHBufC); ... // Use and clean up

// Taking ownership of pre-allocated heap memory TInt maxSizeOfData = 20; RBuf myRBuf;

TUint16* pointer = static_cast<TUint16*>(User::AllocL(maxSizeOfData*2)); myRBuf.Assign(pointer, maxSizeOfData); ... // Use and clean up

As for the Create() methods described above, Assign() will also orphan any data already owned by the RBuf. Close() should be called where appropriate to avoid memory leaks.

The RBuf class doesn't manage the size of the buffer and reallocate it if more memory is required for a particular operation. If Append() is called on an RBuf object for which there is insufficient memory available, a panic will occur. This should be clear from the fact that the base-class methods are non-leaving, meaning there is no scope for the reallocation to fail in the event of low memory.

As with the other descriptor classes, the memory for descriptor operations must be managed by the programmer. The ReAllocL() method can be used as follows:

// myRBuf is the buffer to be resized e.g. for an Append() operation myRBuf.CleanupClosePushL(); // push onto cleanup stack for leave-safety myRBuf.ReAllocL(newLength); // extend to newLength CleanupStack::Pop (); // remove from cleanup stack

Using an RBuf is preferable to using an HBufC in that, if the Re-AllocL() method is used on the HBufC and causes the heap cell to move, any associated HBufC* and TPtr variables need to be updated. This update isn't required for RBuf objects, since the pointer is maintained internally.

The class is not named HBuf because, unlike HBufC, objects of this type are not themselves directly created on the heap. It is instead an R class, because it manages a heap-based resource and is responsible for freeing the memory at cleanup time. As is usual for other R classes, cleanup is performed by calling Close() (or Cleanup-Stack::PopAndDestroy() if the RBuf was pushed onto the cleanup stack by a call to CleanupClosePushL()). See Chapter 4 for a full discussion of Symbian OS R-class types.

It's possible to create an RBuf from an existing HBufC, making it easy to migrate code to use the new class. Because the RBuf class is both modifiable and dynamically allocated, it is desirable to use it where previously it would have been necessary to instantiate an HBufC and then use a companion TPtr object, constructed by calling Des() on the heap descriptor. As can be seen from the following example, the resulting code is simpler and shorter.

Code which previously was written as follows:

HBufC* socketName = NULL;

if(!socketName) {

socketName = HBufC::NewL(KMaxNameLength); // KMaxNameLength is defined

// elsewhere

TPtr socketNamePtr(socketName->Des()); // Create writable 'companion' TPtr message.ReadL(message.Ptr0(), socketNamePtr);

can be converted to the following:

RBuf socketName;

if(socketName,Compare(KNullDesC)==0) {

socketName.CreateL(KMaxNameLength); }

message.ReadL(message.Ptr0(), socketName);

Because the code is simpler, it is easier to understand and maintain. For this reason, RBuf is recommended for use when a dynamically allocated buffer is required to hold data that changes frequently. HBufC should be preferred when a dynamically allocated descriptor is needed to hold data that rarely changes.

The RBuf class was first introduced in Symbian OS v8.0, but first documented in Symbian OS v8.1 and used most extensively in software designed for phones based on Symbian OS v9 and later.

0 0

Post a comment

  • Receive news updates via email from this site