Re: static objects "autoreleased with no pool in place - just leaking"
Re: static objects "autoreleased with no pool in place - just leaking"
- Subject: Re: static objects "autoreleased with no pool in place - just leaking"
- From: Public Look <email@hidden>
- Date: Fri, 13 Feb 2004 13:32:48 -0500
You are using a feature of C++ that does not interact well with
Objective-C. In C and Objective-C, static variables can only be
initialized with constants. No functions, not even objc_msgSend(), can
be called before main() and therefore Objective-C messages can't be
sent before main. By using C++ only features that are enabled by using
Objective-C++, you are breaking a fundamental covenant of C. The
Cocoa framework designers obviously did not account for message sending
and instance creation before main() is called.
I have seen C++ programs that perform 99% of their computation before
main is called. I detest that kind of "magic" that ranks right up
there with template meta-programming. It is worth noting that even C++
does not guarantee the order in which static and/or global variables
will be initialized and any initialization that depends on other
objects already being initialized is error prone and bound to fail.
For example, even if NSColor was a C++ class that used an STL vector to
store already created NSColor instances, there is no guarantee that the
vector will be constructed before it is used by the NSColor constructor
called before mian().
As I recall, the ANSI/ISO C++ specification dedicated many pages to
this issue, and the best advice I can give any C++ programmer is to do
as little as possible before main() is called, avoid static/global
objects that are initialized before main() is called, and only
initialize static/global objects with constant values as opposed to
calculated values that may depend on other objects having been
previously initialized.
It is not particularly relevant, but try this simple C++ program:
#include <stdio.h>
class IAmTrickyA;
class IAmTrickyB;
class IAmTrickyA
{
private:
IAmTrickyB *_b;
public:
IAmTrickyA();
};
class IAmTrickyB
{
private:
IAmTrickyA _a;
public:
IAmTrickyB(IAmTrickyA *aPtr);
};
IAmTrickyA exampleA;
IAmTrickyB exampleB(&exampleA);
int main (int argc, const char * argv[]) {
// insert code here...
printf("Hello, World!\n");
return 0;
}
IAmTrickyA::IAmTrickyA()
{
_b = new IAmTrickyB(this);
}
IAmTrickyB::IAmTrickyB(IAmTrickyA *aPtr)
{
_a = *aPtr;
}
This innocent looking program never gets to main(). The will be "fatal
has exited due to signal 11 (SIGSEGV)." do to the recursive
constructors overflowing the program's stack.
On Feb 13, 2004, at 3:31 AM, m wrote:
>
Yes, that would work but more cumbersome to maintain (static var
>
declaration and accessor multiplied by the number of statics).
>
>
In my case, I'm not trying to emulate class variables, rather I'm
>
setting up a host of colors, fonts, etc. all in one place, that can be
>
referred to symbolically (that is, directly, not through an accessor).
>
This also has the advantage that all values are co-located for easy
>
comparison.
>
>
So for example, at the top of my source file:
>
>
static NSColor* sLabelColor1 = [NSColor colorWithDeviceRed: 0.0
>
green:0.0 blue:0.0 alpha:1.0];
>
static NSColor* sLabelColor2 = [NSColor colorWithDeviceRed: 1.0
>
green:0.0 blue:0.0 alpha:1.0];
>
static NSColor* sLabelColor3 = [NSColor colorWithDeviceRed: 0.0
>
green:0.0 blue:1.0 alpha:1.0];
>
static NSColor* sLabelColor4 = [NSColor colorWithDeviceRed: 1.0
>
green:0.0 blue:1.0 alpha:1.0];
>
static NSImage* sBusyCursorImage = [NSImage imageNamed:@"busy.tif"];
>
static NSImage* sHandCursorImage = [NSImage imageNamed:@"hand.tif"];
>
etc.
>
>
This is the kind of thing that I did all the time in C++, it's hard to
>
believe that no one has figures out a clean way to do it in Obj-C++.
>
>
_murat
>
>
>
On Feb 13, 2004, at 12:06 AM, j o a r wrote:
>
>
> If something hurts, then you should stop doing it... There is more
>
> than one way to skin a cat, as they say.
>
>
>
> Have a look at my last reply for an alternative solution on this
>
> topic.
>
>
From joar's last reply:
>
>> Usually what you would do is something like this:
>
>>
>
>> + (NSMutableDictionary *) myStaticDictionary
>
>> {
>
>> static NSMutableDictionary *theStaticDict = nil;
>
>>
>
>> if (theStaticDict == nil)
>
>> {
>
>> theStaticDict = [[NSMutableDictionary alloc] init];
>
>> }
>
>>
>
>> return theStaticDict;
>
>> }
>
>>
>
>> ...as static variables are often used to "emulate" class variables.
>
>> In the example above the code would typically be executed where an
>
>> autorelease pool has already been set up.
>
_______________________________________________
>
cocoa-dev mailing list | email@hidden
>
Help/Unsubscribe/Archives:
>
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
>
Do not post admin requests to the list. They will be ignored.
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.