Symbian
Symbian OS Library

FAQ-1203 How can I TRAP a 'LC' method/function without causing a panic?

[Index][spacer] [Previous] [Next]



 

Classification: C++ Category: Memory Management & Cleanup
Created: 01/06/2005 Modified: 08/03/2005
Number: FAQ-1203
Platform: Not Applicable

Question:
In my code I need to TRAP a 'LC' method/function but I understand doing this directly results in an application panic. How can I achieve this result without causing a panic?

Answer:
How can I TRAP a 'LC' method/function without causing a panic ?
    See FAQ-1195 for reasons on why a 'LC' method cannot be trapped directly.

    Objects pushed on the CleanupStack without a matching pop are considered to be orphaned at the point when the TRAP is untrapped i.e. if the method does NOT leave and returns normally. Leaving orphaned objects on the CleanupStack is a programming error; hence, the E32USER-CBASE 71 panic is issued as a severe run-time fault.
    Are there any (work-around) solutions for TRAPing a 'LC' method?

      If you have to TRAP a 'LC' method for any reason, for example, you are fixing some code defect, retrofitting code (implementing new features over existing code) etc, then you can use the following solutions as work-arounds:
        • TRAP the calling method (if it can leave) in which the 'LC' method is invoked. The idea is to place the TRAP somewhere along the execution path before the 'LC' method is called. This should avoid TRAPing the 'LC' method and still TRAP an exception - though at a different point to where the 'LC' method is executed.
        • TRAP the 'LC' method followed by a Pop(). The idea is to encapsulate the call to the 'LC' method and the Pop() in one TRAP harness. For example:

        HBufC* buf = NULL;
        TRAPD(error,
        buf=GetSomeDetailsLC();
        SomeMethodL(buf);
        CleanupStack::PopAndDestroy(buf);
        );
          As the buffer is popped within the TRAP block i.e. before the TTrap is untrapped, the panic will not transpire when the 'LC' method returns normally.
          You can equally just Pop() the buffer immediately after the 'LC' method and perform operations on it outside the TRAP block. Note that if you are going
          to pass a pointer placeholder to the buffer as a parameter to the 'LC' method (instead of receiving it as a return parameter), ensure that the 'LC' method
          is defined to take a reference to a pointer e.g. GetSomeDetailsLC(HBufC*& aBuf) - else calling CleanupStack::PopAndDestroy(buf)
          will result in a E32USER-CBASE 90 panic.
          • If the method from where you are calling the 'LC' method is a non-leaving method (this appears to be the main reason for TRAPing a 'LC' method) then create a new method/function e.g. TrapAndLeaveL() method, TRAP it in the non-leaving method in place of the 'LC' method. In the TrapAndLeaveL() method call the 'LC' method without TRAPing it, handle the new object (do operations on it) and pop (and destroy) the object before returning.

          void TrapAndLeaveL() {

          pointerToSomething = MyObject::NewLC(); // No TRAP
              pointerToSomething->SomeMethodL();
              ...
              ...
              CleanupStack::PopAndDestroy(pointerToSomething ); }

              In the invoking non-leaving method call the above method....

              TInt err = KErrNone;

              TRAP(err, TrapAndLeaveL());
                  if (err != KErrNone) {
                  err = SomethingElse();
                  }
                  ...
                  ...
                  return err;
                  • Change (if you have access to) the 'LC' method to just a leaving method and push the object in the calling method once the object is returned. Assume the below is called from a leaving method.

                      TRAP(err, pointerToSomething = MyObject::NewL()); // Does NOT push

                      // or check 'pointerToSomething'
                      //
                      if (err != KErrNone) {
                      SomethingElseL();
                      }
                      else {
                      CleanupStack::PushL(pointerToSomething); // Push the object here
                      pointerToSomething->SomeMethodL();
                      ...
                      ...
                      CleanupStack::PopAndDestroy(pointerToSomething );
                      }