Hi, I'm Paul, but you can also call me Todd and I won't get upset.
Paul.Todd | 14 November, 2006 22:35
Someone emailed me a while back on how to use CStack. A quick search of the devkit with Copernic search showed no examples so I decided to post some code on how to use it.
The Symbian implemenent of a stack is a simple array where items are appended to the end of the array. This is both simple, elegant and unobtrusive.
First decide if the stack is to hold pointer or structures.
If the array is to hold pointers, then does the array own the pointer? Normally the answer is yes.
Lets say we want to create a stack of strings, then these strings would be implemented as HBufC's
so to make life easier, when a string is on the stack, the stack owns the the string.
So the stack can now be declared as (note the stack owns the data it contains!):
CStack<HBufC, ETrue>* myStack = new (ELeave) CStack<HBufC, ETrue>;
As we have declared it on the heap, we need to remember to push it onto the cleanup stack
so that if there is a leave it get cleans up nicely.
CleanupStack::PushL(myStack);
To add an item onto the stack is simple
_LIT(KFirstItemOntoTheStack, "My First Item");
myStack->PushL(KFirstItemOntoTheStack().AllocL());
Here we create a copy of KFirstItemOntoTheStack and then put it onto the stack, note
that at all times it is leave safe and nothing leaks if for example PushL fails.
This is because when we created the stack class we told it that it owns all the memory
Of course now we can get the top item, which returns an HBufC*
HBufC* top = myStack->Head();
and check to see if the stack is empty
if (myStack->IsEmpty())
{
// do something
}
There are also the usual Pop to remove the top item (but not delete it!) and Head to get the top item,
which for some reason is not declared as Top, like my CS 101 class taught, go figure?
Now we have finished with the stack, we can delete it, this also deletes all the items
owned by the cleanup stack.
CleanupStack::PopAndDestroy(myStack);
This is a pretty good implementation and to be be quite honest the only thing I would really like to see
would be for it to be an R class derived from RPointerArray.
Now for a little quiz:
What is wrong with this code?
struct TMyVersionStruct
{
TUint32 iVersion;
TUint32 iItem1;
TUint32 iItem2;
TUint32 iItem3;
TUint32 iItem4;
TUint32 iItem5;
TUint32 iItem6;
};
LOCAL_C void TestCrash()
{
// The production code reads a blob from disk and it looks correct
// in the debugger but it itermittantly crashes,
// here however we simulate what the read from disk as the problem
// is not in the reading...
HBufC8* item = HBufC8::NewL(sizeof(TMyVersionStruct));
item->Des().SetLength(item->Des().MaxLength());
TMyVersionStruct version;
TPtr8 ver((TUint8*)&version, sizeof(version));
ver = *item;
delete item;
// do something with version
}
Its an interesting if very subtle problem that seems to come up when memory is very fragmented and is
fiendishly annoying.
Answers next week.....
You must login to post comments.
Login