You Are Here:

Community: Developer Discussion Boards

Reply « Previous Thread | Next Thread »

#16 Old Re: Why exactly ConstructL is needed? - 2008-05-03, 20:01

Join Date: Mar 2007
Posts: 103
Location: Brazil
cabezonxdg
Offline
Regular Contributor
If i got the point, there´s another solution to handle this:

http://www.parashift.com/c++-faq-lit....html#faq-17.4


Wiki Contributor of the Month (May).
Winner of the May Contest on Wiki.
Reply With Quote

#17 Old Re: Why exactly ConstructL is needed? - 2008-05-04, 19:00

Join Date: Aug 2004
Posts: 295
simo.salminen
Offline
Regular Contributor
Quote:
Originally Posted by cabezonxdg View Post
If i got the point, there´s another solution to handle this:

http://www.parashift.com/c++-faq-lit....html#faq-17.4
True. You can write Symbian today without two-phase construction / leaves / cleanupstack. Only issue is integrating with existing code and with Symbian APIs.
Reply With Quote

#18 Old Re: Why exactly ConstructL is needed? - 2008-05-04, 19:25

Join Date: Aug 2004
Posts: 295
simo.salminen
Offline
Regular Contributor
My summary:

Lets recap.

Original issue was that why this code does not work:

Code:
"""
CWidget::CWidget()
{
CleanupStack::PushL(this);
iDoodad=new(ELeave) CDoodad;
iWotsit=new(ELeave) CWotsit;
CleanupStack::Pop();
}

//usage:
CWidget* x=new(ELeave) CWidget;
CleanupStack::PushL(x);
x->FooL();
CleanupStack::PopAndDestroy(x);
"""
The explanation given by 9200 SDK tech. paper said:
Quote:
This might work in some situations, but not in others, because of lifetime issues during the constructor, and rules about the order of base class construction.
Further investigation in this thread has shown that actually this code SHOULD work in original epoc/symbian code that does not have c++ exception handling enabled. When c++ exception handling is enabled as it today in s60v3, code does not work. It does not work because if leave occurs in constructor, base class destructors are called twice.

Why? When User::Leave occurs in derived class constructor, it will cause cleanup stack to be destroyed on that level. This will cause destructors to be called for the class and its bases. After cleanup stack is cleaned, the User::Leave will throw exception (XLeaveException). Because of the C++ rules, this will cause call to already constructed base class destructors. When base class destructor is attempted to run again, it will cause crash, because the object has already been destroyed.

The original explanation is bit unclear. It makes sense if one assumes that the original designers saw at the time, that if someday c++ exceptions are enabled, this would be a problem.

So it seems that even though Symbian didn't have c++ exception handling at the time, the designers were smart enough to future-proof the design.

IMO Symbian has one of the best exception/error handling mechanisms, and this is further proof that it is really well thought out.


Lets further speculate what would happen if this design pattern would have been chosen at the time:
- As mentioned, it would not have been future-proof. One would not have been able to enable c++ exceptions in Symbian because it would have caused major code re-write.
- Using BaseConstructL/ConstructL pattern is slighly more efficient than PushL/Pop in base and child class.
- It would have violated the L suffix naming convention (unless one would have renamed the classes with L which would have been somewhat ugly).
- If ctors could leave, there is issue with "C* c = new C();". This kind of code would have required TRAP (new does not leave, but the ctor can, so error checking is bit complicated).
- According to C++ rules, object lifetime starts when its constructor is executed succesfully. Calling object destructor before its lifetime has started could lead to some weird problems in some special cases. Note that this destructor calling before lifetime is started is what happens if object is pushed to cleanup stack in constructor and leave occurs.

However, there is at least couple upsides if this pattern would have been chosen:
- Simpler (no two-phase construction).
- I've seen code where allocation is done in ctor (in a way that it does not leave). If OOM occurs, a flag is set. Then this flag is checked in all member functions, and they leave if the initial memory allocation in ctor has failed. Its kind of "deferred leaving". I think this was an existing base class, so adding (Base)ConstructL is not possible without API break. Interesting speculation is that if ctor would be allowed to leave, this change could have been done without this "deferred leaving".


Thanks to all for your comments and bringing clarity to the issue!
Last edited by simo.salminen : 2008-05-15 at 10:50. Reason: clarified the reason why it crashes, also added one more reason why it should not be used
Reply With Quote

#19 Old Re: Why exactly ConstructL is needed? - 2008-06-19, 15:06

Join Date: Dec 2006
Posts: 2,094
Sorcery-ltd's Avatar
Sorcery-ltd
Offline
Forum Nokia Champion
Hi,

I'm rather late to the party on this thread - only just saw it via the latest code clinic on SDN.

I've actually been asking this very question for years in various training courses. One additional answer I got that did actually make sense (and is part of the reason why we have leaves and the cleanup stack at all) is that Symbian (EPOC32 as it was then) was first developed when C++ was very new and the compilers were far from standard in their behaviour. The pattern discussed here to avoid 2-phase construction worked on some compilers and not others (which is probably the origin of the vague explanation in the old SDK).

Sorcery
Reply With Quote

#20 Old Re: Why exactly ConstructL is needed? - 2008-06-19, 15:32

Join Date: Apr 2005
Posts: 1,668
Location: Barcelona
david.caabeiro's Avatar
david.caabeiro
Offline
Forum Nokia Champion
Mark,

Good to bring this thread back, I had also missed it..

Personally, I'd rely on smart pointers and throw exceptions in the constructor.. this is closer to standard C++ and I think we're at the right time to start using these idioms, at least for engine code (and of course, provided you work solely on 3rd edition). On some other code (like UI) that relies heavily on Symbian idioms could still need to rely on this..

Also, having OpenC++ available now, Boost provides excelent smart pointers implementations (scoped, ref counted, etc..)
Reply With Quote

#21 Old Re: Why exactly ConstructL is needed? - 2008-06-20, 10:59

Join Date: Nov 2005
Posts: 581
Location: London
stichbury's Avatar
stichbury
Offline
Super Contributor
Quote:
Personally, I'd rely on smart pointers and throw exceptions in the constructor.
There's a problem with this though. If your constructor leaves/throws you risk leaking the memory allocated to hold the object itself.

If you implement CWidget such that the constructor leaves, and then call

CWidget* widget = new CWidget();

You find the memory for widget is freed by C++ exception processing (and if you use smart pointers within CWidget, then anything the constructor allocates is freed).

But if you use

CWidget* widget = new (ELeave) CWidget();

then bang! If CWidget() leaves, you get an ALLOC panic, for the memory allocated to store widget.

So it's a bit risky to rely on standard behaviour when, at present, Symbian OS doesn't guarantee it.
Reply With Quote

#22 Old Re: Why exactly ConstructL is needed? - 2008-06-20, 11:01

Join Date: Nov 2005
Posts: 581
Location: London
stichbury's Avatar
stichbury
Offline
Super Contributor
PS: The code clinic Sorcery referred to is here: http://developer.symbian.com/main/su...2008/index.jsp

I don't cover the point I mentioned above because it complicated the issue and strayed too far from the original thread. But I think it's worth mentioning...
Reply With Quote
Reply « Previous Thread | Next Thread »
Display Modes
Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules

You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are Off
[IMG] code is On
HTML code is Off
Forum Jump
Similar Threads
Thread Thread Starter Forum Replies Last Post
Form not displayed when is created in Container ConstructL redbart Symbian User Interface 2 2008-04-01 11:30
Tool to find the needed capabilities gaurav C Symbian Tools & SDKs 4 2008-03-25 13:30
beginner's question:difference between ConstructL and BaseConstructL 021850524 General Symbian C++ 3 2007-07-19 10:54
How to set number for forwarding?? silviuccia General Symbian C++ 6 2007-01-09 11:16
help needed rajiv_614 General Browsing 2 2006-04-17 12:56

Rate This

 
Bookmark this page: DeliciousDiggFacebookGoogleYahooStumbleUponRedditDiigoTechnocratiTwitter  Share this page Share this page Print this Page Print this page Invite a friend Invite a friend
京ICP备05048969号    Email Newsletters Press Terms & Conditions Privacy Policy Sitemap Contact Us © 2010 Nokia