Why CleanupStack::PushL(CBase*) and not CleanupStack::PushL(CBase*&)?

Login to reply to this topic.
Mon, 2005-08-29 18:05
Joined: 2005-06-13
Forum posts: 68
Hi there,

You've probably noticed that the CleanupStack PushL methods take a pointer by value instead of taking a pointer by reference.  In my humble opinion it would make more sense if they were passed by reference.  Ok, one of the results of that would be that you couldn't pass a temporary to PushL, but then when would you ever need to do that?

Because PushL takes pointers by value the following (useless) example is broken:

TInt method(HBufC*& aBuf)
{
   aBuf = _L("Hello").Alloc() ;
   return 0 ;
}

HBufC* buf = NULL ;
CleanupStack::PushL(buf) ;
method(buf) ;
// now buf points to "Hello"
CleanupStack::PopAndDestroy(buf) ;  // this causes a panic because buf now points to something else


Anyone can find a good reason why the PushL methods don't take pointers by reference?

Thanks,

Nikolas.



If we fall down it's so we can learn to pick ourselves up.


Wed, 2005-08-31 09:30
Forum Nokia Champion
Joined: 2003-10-01
Forum posts: 723
Re: Why CleanupStack::PushL(CBase*) and not CleanupStack::PushL(
That would be a very ugly solution! Cleanup stack always pops the same item than what was pushed onto it regardless of the fact if the pointer points to a different object or not. If it does, then the new object can also be pushed so that you can use the same pointer to push more than one object to the cleanup stack and you can be sure that the right object will be popped (and destroyed).

Nevertheless, I must admit that the special use case you mentioned below does not work. This way. Note that passing the expected item (i.e. the pointer) is a useful trick for debugging, but usually not used in a release (i.e. urel) build. And to be honest, I've never met such an expectation that I push sg onto the stack and expect the stack to pop sg else, just because the value of the pointer has changed in between. That's the reason why I said that it's a very special use case.

Cheers,

tOtE

Gabor Torok
Software architect, Agil Eight (http://www.agileight.com/)
Blog: http://mobile-thoughts.blogspot.com/

Wed, 2005-08-31 11:19
Joined: 2005-07-01
Forum posts: 12
Re: Why CleanupStack::PushL(CBase*) and not CleanupStack::PushL(
the CleanupStack must also clear heap memory on Eleave. This is possible only if it have the pointer to cell in to heap!!

www.italiasymbian.it for italian development
Wed, 2005-08-31 12:29
Joined: 2004-11-29
Forum posts: 1242
Re: Why CleanupStack::PushL(CBase*) and not CleanupStack::PushL(
The good reason is the cleanupstack doesn't care about your pointer, it only cares about the object your pointer points too.

The cleanupstack exists so it can destroy objects you have created, either temporary with a lifespan only in one function, or ones you not yet can save the pointer too in a member variable, if a leave occours

Its not meant as a way to keep track of your pointers, its ment to ensure that objects get destroyed properly and it can't do that with a reference to a pointer...
It needs a pointer to the actual object.

If you don't have any possibly leaving L-functions between the allocation of the object, and the destruction, you don't need the cleanupstack at all!

Here is an (fully sane) example that wouldn't work with saving a ref. to a pointer:

Code:
void copybitmap() {
iBitmap2 = new (ELeave) CFbsBitmap();
iBitmap2->Create(iBitmap1->SizeInPixels(),iBitmap1->DisplayMode());

CFbsBitmapDevice* fbsdev = CFbsBitmapDevice::NewL(iBitmap2);
CleanupStack::PushL(fbsdev);
CFbsBitGc* fbsgc = CFbsBitGc::NewL();
CleanupStack::PushL(fbsgc);
fbsgc->Activate(fbsdev);
fbsgc->BitBlt(TPoint(0,0),iBitmap1);

CleanupStack::PopAndDestroy(2); //pop from cleanupstack and destroy fbsgc, fbsdev
}

Say here that CFbsBitGc* fbsgc = CFbsBitGc::NewL();   leaves because of Out of memory.
Since the fbsdev pointer variable is on stack, it will no longer exist when the code in the TRAP harness, going through the cleanupstack runs.
So any reference saved to it would not longer be valid, and the CFbsBitmapDevice object would be lost, resulting in a memory leak.
(and most possibly a crash in the cleanupstack code, since it would be very hard to check for this case)

  • Login to reply to this topic.