User::Leave() side effects

Login to reply to this topic.
Mon, 2008-02-18 19:23
Joined: 2005-11-29
Forum posts: 15

Hi!
I understand that the second phase constructor was designed to handle "exceptions" when constructing an object, but, what is it supposed to do in that case??
I would like to notify the exception, but if I call User::LeaveNoMemory() in the ConstructL() of an object i.e., when I try to show a dialog after the TRAPD() call, the app crashes with KERN-EXEC 3 panic.

This is an example code:

void CMyAppUi::ConstructL()
{
  CMyObject *obj;
  TRAPD( err, obj = CMyObject::NewL() );
       
  if ( err == KErrNoMemory )
  {
    // KERN-EXEC 3 !!!
    CEikonEnv::Static()->InfoWinL( _L( "Text 1" ), _L( "Text 2" ) );
  }
}

void CMyObject::ConstructL()
{
  iBuf = (TUint8*)User::Alloc( 32*1024*1024 ); // Enough memory to crash
       
  if ( !iBuf )
  {
    User::LeaveNoMemory();
  }
}

If err = KErrNone, I can show a InfoWinL() dialog without problems.
Any idea about how to avoid this side effects of User::Leave() ???

Thanx in advance.


Mon, 2008-02-18 20:36
Joined: 2003-09-29
Forum posts: 32
Re: User::Leave() side effects

Have you tried running only the crashing code, ie. CEikonEnv::Static()->InfoWinL( _L( "Text 1" ), _L( "Text 2" ) ); inside the ConstructL? I suspect that it crashes alone as well. You should call BaseConstructL of you appui base class before doing anything else in the appui ConstructL method. I think BaseConstructL initialises the needed values and eikonenv.


Jari

Tue, 2008-02-19 09:51
Joined: 2005-11-29
Forum posts: 15
Re: User::Leave() side effects

Yes, I tried.
And I checked that th BaseConstructL() call is previous.

If I change this code, the second call goes succesfully:

void CMyAppUi::ConstructL()
{
  CMyObject *obj;
  TRAPD( err, obj = CMyObject::NewL() );
      
  if ( err == KErrNoMemory )
  {
    // KERN-EXEC 3 !!!
    CEikonEnv::Static()->InfoWinL( _L( "Crash" ), _L( "" ) );
  }
  else if ( err == KErrNone )
  {
    CEikonEnv::Static()->InfoWinL( _L( "Ok" ), _L( "" ) );
  }
}

Thank you for your answer anyway.

Tue, 2008-02-19 13:18
Joined: 2005-11-29
Forum posts: 15
Re: User::Leave() side effects

Sorry.
I'm afraid the info I posted is insuficient. I tried the simple example that I wrote in this post, and it works fine.
In my "actual code" the object that throw the User::Leave() "exception" is not a member of CMyAppUi directly, but there is a sequence of 4 objects untill the one that crashes.
I noticed that the code after User::Leave() never executes, so all the constructors return NULL pointer ('cause the construction never ends, I think).
So I think my problem is somewhere in the constructors of all the sequence of objects.
Anyone, maybe somebody has an idea about what could be the problem, because my objects in theory are independent of the CEikonEnv::Static()->InfoWinL() call, and, in theory, it doesn't matter if they are created successfully to show a dialog.

PS. Most of my objects extends from CActive, and makes a CActiveScheduler::Add() call at the beginning of their ConstructL()'s.

Thanx again.

Tue, 2008-02-19 14:47
Joined: 2003-12-05
Forum posts: 622
Re: User::Leave() side effects

...I noticed that the code after User::Leave() never executes, so all the constructors return NULL pointer ('cause the construction never ends, I think).

The constructor should never cause a leave in Symbian. That's why the two phases. If constructor leaves, the object is not constructed, obviously. Anything constructed before leaving, though, is successfully done and may (probably will) cause memory leaks.

Tue, 2008-02-19 17:41
Joined: 2005-11-29
Forum posts: 15
Re: User::Leave() side effects

Ok.
But, if I have objects that alloc memory, and the allocation fails, what am I suppused to do???
I just want to let the AppUi know about the failure to notify the user about it, and I thought that Leave() and TRAP() was a good method.
I could create the objects without memory allocation, and after that ask for memory with some Init() method, but it seems dirtier to me.
Any suggestion?

Tue, 2008-02-19 18:29
Joined: 2003-12-05
Forum posts: 622
Re: User::Leave() side effects

The idioms of two phase construction, leave and the cleanup stack are just the tools for this!

See classic NewL, for example:

CMyClass * CMyClass::NewL()
{
  CMyClass * self = new (ELeave) CMyClass;
  CleanupStack::PushL(self);
  self->ConstructL();
  CleanupStack::Pop(); // self
  return self;
}

Constructor cannot leave. Now, ConstructL can leave, but if it does, the error handling system (part of TRAP/D) empties the cleanup stack and deletes your object. In your CMyClass destructor you delete/release all dynamically allocated member variables, not assuming successful creation of object. If ConstructL does not leave, you have a properly allocated object and you can take your object out of the cleanup stack.

If you have CMyClass as a member variable, you know if it has been successfully allocated or not. If the pointer is NULL, it has not been allocated. If it is something else, it has. All CBase based objects' member data is initialized to zero (NULL, 0) or the default constructor is called (non-pointers and native data types), so you can be sure of this.

Though, if your code leaves in CYourAppUi::ConstructL, then the application startup fails and your app will not be launched at all. This you can solve in different ways. You can just leave it like that -- if the initialization fails, there is no change the app could work, so it's better to quit. Or, you can try lazy initialization -- let the app start, but do the initialization later. E.g. in startup, launch a one shot timer and do the initialization only when the timer fires (e.g. 0.2 secs after app has launched). Then the app is already running and if the initialization fails, you can show some error code to let the user know something is not right. Or try to implement something to solve the problem in the application code (try again, do alternative stuff,..).

  • Login to reply to this topic.