CBase operator new on a class on the stack

Login to reply to this topic.
Mon, 2006-02-06 18:00
Joined: 2004-05-29
Forum posts: 149
One of the few things that I've liked about Symbian is the overridden operator New of the CBase class.  It sets all of your member variables to 0 or NULL, so you don't have to worry about setting all of your member variables yourself in the constructor(s).

However, if I have a CBase class on the stack, such as:

Code:
class CClass : CBase {
public:
void DoSomething()
private:
int iX; // expect this to be 0 on creation since this is CBase class
char* iY; // ... ditto ...
};

// ...

MyMethod() {
CClass myClass1;
myClass1.DoSomething(); // member variables NOT init'ed
CClass* myClass2;
myClass2 = new(ELeave) CClass; // member variables init'ed
myClass2->DoSomething();
}

In the DoSomething() method, myClass1's member variables are not set to 0.  This seems counterintuitive to me.  If I cannot rely on the fact that CClass's variables will always be set to 0, I have to go back in all of my CBase class constructors, and put in the member variable initilization in there anyways!  Making CBase's overriding the new operator misleading (and potentially dangerous, since your variables are initialized only some of the time!)  Is there something I'm missing here!
-euroq

Mon, 2006-02-06 18:40
Joined: 2004-10-31
Forum posts: 92
Re: CBase operator new on a class on the stack
>Is there something I'm missing here!

Yes.  C classes should never be stack-based.  You must always create them on the heap.
Mon, 2006-02-06 19:46
Joined: 2003-10-15
Forum posts: 78
Re: CBase operator new on a class on the stack
Symbian programming is based on conventions a lot.
You must declare leaving function with the L letter, you must always "Close" R-classes, you must instantiate C-classes only on the heap, etc.

And one more rule. It is not that strict, nevertheless, you should not use new (Eleave) operator at all, you should keep the constructor protected and use the factory functions NewL and/or NewLC for instantiation.

I cannot recall it clearly, but I think, that CBase constructor is also protected

Mon, 2006-02-06 20:46
Joined: 2004-05-29
Forum posts: 149
Re: CBase operator new on a class on the stack
I understand.  The answer is that C-classes must always be instantiated on the heap, never on the stack.

So, quick question: Does anyone who writes Symbian programs ever make classes that don't follow the rules of C, R, and T classes?  After all, if I don't have a Close() method it's not an R-class.  If I want a simple storage class, but it holds its own heap data (owns its own pointers), it can't be a T class.

Seems rather inefficient to take the code that once used classes on the stack, and change them to heap, since the memory allocation just wastes time.
Mon, 2006-02-06 20:58
Joined: 2003-10-15
Forum posts: 78
Re: CBase operator new on a class on the stack
Quote from: euroq
So, quick question: Does anyone who writes Symbian programs ever make classes that don't follow the rules of C, R, and T classes?
Can't say for everybody, but in my company it is prohibited by internal standards (and AFAIK by Symbian conventions also).

Quote
After all, if I don't have a Close() method it's not an R-class.
R-classes are not exactly about the Close() - it's only a consequence. R-classes represent handles to the kernel objects. They don't allocate any heap in your thread(s), but the corresponding kernel servers do allocate. Close() lets them free the kernel-side resources.

Quote
If I want a simple storage class, but it holds its own heap data (owns its own pointers), it can't be a T class.
.
Allocates memory = C-class and that's it. Of course, if you want to use the CleanupStack protection against memory leaks Wink

Quote
Seems rather inefficient to take the code that once used classes on the stack, and change them to heap, since the memory allocation just wastes time.
Sounds very similar to the "root of all evil" - premature optimization Smiley

You don't have to allocate everything on the heap. You can keep everything allocated on stack and then you don't need cleanup stack. It is not recommended practice since Symbian devices usually have very small stack size, but if it just about couple of ints, you can do it.

Mon, 2006-02-06 22:18
Joined: 2004-05-29
Forum posts: 149
Re: CBase operator new on a class on the stack
Quote
R-classes are not exactly about the Close() - it's only a consequence. R-classes represent handles to the kernel objects. They don't allocate any heap in your thread(s), but the corresponding kernel servers do allocate. Close() lets them free the kernel-side resources.
Yeah, I was skimming by that part  Grin


Quote
Allocates memory = C-class and that's it.

So, just to clarify:
Code:
MyMethod() {
CClass myClass1;
myClass1.DoSomething(); // member variables NOT init'ed
}

... Is extremely against Symbian "conventions" and the real answer to my original question is, you just aren't supposed to do that... you can, but when you break conventions you have problems like I mentioned with the CBase new operator not being called to clear out your member variables.

Thanks everyone,
-euroq
Tue, 2006-02-07 00:51
Joined: 2004-10-31
Forum posts: 92
Re: CBase operator new on a class on the stack
Another significant problem is that C classes are designed to *own* handles and other objects, and are responsible for clean up.  If you put a C class object on the stack and a leave occurs, the destructor of the C class won't get called and cleanup will not occur.

So T classes are any classes that can safely be created on the stack because they are leave safe.  C classes are those that cannot be.  You can break the rule and put a C class object on the stack if you can guarantee it will not leak if a leave occurs. 

In effect, you either prevent leaves from occurring (ie use TRAPs or never call leaving code) or you make the class leave safe by not taking ownership of other objects (ie, it becomes the same as a T class).

If you break the rules you also have to guarantee that your callers understand this, and that anyone maintaining the code in future knows it too.  It's just too much hassle really, and this is the reason why the convention is there.  Not to restrict you, but so no misunderstandings occur  Smiley


Tue, 2006-02-07 14:06
Joined: 2003-10-10
Forum posts: 124
Re: CBase operator new on a class on the stack
You should always create C-classes on the heap. This way they will always have member variables set to zero.

CSomeclass* myInstance = new (ELeave)CSomeClass;

CleanupStack::PushL(myInstance);

blah blah

CleanupStack::PopAndDestroy(); // myInstance
  • Login to reply to this topic.