Returning TBuf as automatic variable - not possible?

Login to reply to this topic.
Tue, 2004-11-23 09:41
Joined: 2004-11-09
Forum posts: 20
I have a method in which I define a TBuf<20> (stack-based). I want to return exactly this Tbuf, as an automatic, stack-based copy. Simple and plain... but it doesn't work! It seems that my data in the descriptor gets mixed up somehow, you can see some things while debugging, but it's not an identical copy!
I did it like this way:

TDes foo()
{
TBuf<20> output;
//... output gets properly (!) filled
return output;
}

called like this:
TBuf<20> input;
input = foo();

I don't want to use references, because these TBufs (in different classes) should be totally independent and merely copies.

What's wrong? Sad I've tried almost everything it seems to me! The problem maybe is related to http://forum.newlc.com/viewtopic.php?t=172&highlight=return+tbuf

Tue, 2004-11-23 11:35
Forum Nokia Champion
Joined: 2003-10-01
Forum posts: 723
Returning TBuf as automatic variable - not possible?
It's a coding convention that your function must NEVER return a local variable. Simply, your output variable gets invalid after you've returned from the function. Note that you may return a TDes from foo() if that descriptor operator on a data member, which exists even after the function call. That would ensure that the descriptor points to a valid data.

Another solution:
Code:
TInt GetFoo( TDes& aBuffer )
   {
   TInt error = KErrNone;

   // Here you have to fill aBuffer properly
   // If an error occured, handle it by using 'error' variable properly

   return error;
   }

TBuf<20> input;
User::LeaveIfError( GetFoo( input ) );

It's that simple.

Cheers,

tOtE

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

Tue, 2004-11-23 11:55
Joined: 2004-11-09
Forum posts: 20
Returning TBuf as automatic variable - not possible?
Thank you very much!
 Embarassed stupid mistake  Sad

BUT anyway - I wonder why you can return the TInt you defined in the function easily - doesn't it go out of scope, too (because you said:"you must NEVER return a local variable") ? What's the difference between the TInt and let's say my TBuf? Both are a local variable!? I always thought it's just a copy that gets passed! (??)
 Roll Eyes  Huh:
Tue, 2004-11-23 12:48
Forum Nokia Champion
Joined: 2003-10-01
Forum posts: 723
Returning TBuf as automatic variable - not possible?
That is true, a copy of these values will be returned. BUT, you returned a TDes, which is only a descriptor and the main difference between TDes and TBuf is that while TBuf contains the referenced data as well, TDes only points to it. That is, in your TDes you pointed to a data, which was out of scope, since output variable is invalid outside the foo() function.

If you want to keep the original behavior, then you will have to slightly modify the return value from TDes to TBuf. Like:
Code:
TBuf<20> foo()
   {
   TBuf<20> output;
   // ...
   return output;
   }

That would ensure that a copy of the whole buffer will be returned.

Is it clear now? Wink

tOtE

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

Tue, 2004-11-23 15:04
Joined: 2004-11-09
Forum posts: 20
Not everything goes the other way round!
Ah okay! I understand... Thank you! And I will try both solutions soon.
Somehow the SDK gave me not that presentation of things you did   Sad - I did not realize that TDes loses its data on returning because using it as argument goes fine...!!  Roll Eyes

BTW: The second variant is not so fast as the first one (passing by reference), isn't it?
Tue, 2004-11-23 16:49
Forum Nokia Champion
Joined: 2003-10-01
Forum posts: 723
Re: Not everything goes the other way round!
Quote from: animage
BTW: The second variant is not so fast as the first one (passing by reference), isn't it?

You're right. Passing a reference means passing a pointer, which means - in a 32-bit architecture - 4 bytes.

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

Tue, 2004-11-23 23:42
Joined: 2004-11-21
Forum posts: 33
Re: Returning TBuf as automatic variable - not possible?
Quote from: animage
I have a method in which I define a TBuf<20> (stack-based). I want to return exactly this Tbuf, as an automatic, stack-based copy. Simple and plain... but it doesn't work! It seems that my data in the descriptor gets mixed up somehow, you can see some things while debugging, but it's not an identical copy!
I did it like this way:

TDes foo()
{
TBuf<20> output;
//... output gets properly (!) filled
return output;
}

called like this:
TBuf<20> input;
input = foo();

I don't want to use references, because these TBufs (in different classes) should be totally independent and merely copies.

What's wrong? Sad I've tried almost everything it seems to me! The problem maybe is related to http://forum.newlc.com/viewtopic.php?t=172&highlight=return+tbuf
There is in my opinion a bug in the interface to TDes in that it does not have a protected copy constructor.  Since the TDes and TDesC classes are "abstract" classes you should never be able to concretely instantiate any of them.  You should use only see TDes& or TDes* in appropriate situations.  If you see them used straight off then youÂ’re asking for run-time trouble.

You could of course write something like this:
Code:
TBuf<20> Foo()
{
 TBuf<20> output;
//
 return output;
}
And still call it with
Code:
TBuf<20> input( Foo());
without any great overhead given what the C++ standard allows to compiler to implement.

Regards, Bo

Sat, 2006-11-04 18:54
Joined: 2006-11-04
Forum posts: 2
Re: Returning TBuf as automatic variable - not possible?
FYI - This might help ...   Afro
===

from: http://descriptors.blogspot.com/2005/05/9-how-do-i-use-descriptors-as.html

My function uses TDes or TDesC parameters like you say, but my descriptor passing doesnÂ’t work. Why not?

Oh how much pain has this one caused? Missing out that little & symbol makes all the difference. Your parameter types must be references, not values, ie const TDesC& or TDes&.

The base classes TDesC and TDes contain no string data. If you pass them by value rather than by reference, you are using static binding, which means that polymorphism wonÂ’t work, and you'll end up with a data-free base class object. It will all compile OK, but nothing works.

Never attempt to instantiate or work directly with objects of the base classes TDesC or TDes, as Tip 1 advises. They are effectively abstract classes. There is rarely, if ever, a valid reason for instantiating them rather than an object of their deriving classes (TBufC, TBuf, TPtrC, TPtr, HBufC or RBuf).
Sat, 2006-11-04 22:58
Joined: 2004-11-21
Forum posts: 33
Re: Returning TBuf as automatic variable - not possible?
Quote from: mytimepass2002
...
Never attempt to instantiate or work directly with objects of the base classes TDesC or TDes, as Tip 1 advises. They are effectively abstract classes. There is rarely, if ever, a valid reason for instantiating them rather than an object of their deriving classes (TBufC, TBuf, TPtrC, TPtr, HBufC or RBuf).

The only possible reason would be to just keep know the length descriptor, TDesC, or length and max length, TDes.  Any use of the instance would render undefined behaviour.

But still, NEVER instantiate them!  In the future any code with concrete TDesC/TDes variables will not compile. Check it out by adding a protected copy constructor to TDesC and TDes (inline implementation needed of course).

Regards, Bo

  • Login to reply to this topic.