views:

190

answers:

4

When I check a singleton property that is nil, it kills my app. But when I check for nil on a class instance property, everything works fine.

This works fine:

self.MyProperty == nil

but this will kill the app with “EXC_BAD_ACCESS”

[MySingleton sharedManager].SomeProperty != nil

What is the difference with the singleton that I can't check for nil?

Here's the singleton implementation:

.h file:

@interface MySingleton : NSObject {
    NSString * SomeProperty;
}
@property (nonatomic, copy) NSString * SomeProperty;
+(MySingleton *)sharedManager;
@end

.m file:

#import "MySingleton"

static MySingleton *sharedManager = nil;

@implementation MySingleton
@synthesize SomeProperty;

- (void)dealloc {
     [SomeProperty dealloc];
     [super dealloc];
}

+(MySingleton *)sharedManager
{       
    if (!sharedManager){
         sharedManager = [[MySingleton alloc] init];
    }
    return sharedManager;   
}

This is what I find in the console when when trying to assign something to SomeProperty:

MyApp(51363,0xa0389500) malloc: *** mmap(size=2147487744) failed (error code=12)
*** error: can't allocate region  
*** set a breakpoint in malloc_error_break to debug
Current language:  auto; currently objective-c  
(gdb) break malloc_error_break  
Note: breakpoints 6 and 8 also set at pc 0x929c2072.
Breakpoint 11 at 0x929c2072  
(gdb) continue  
(gdb) po [MySingleton sharedManager].SomeProperty
Cannot access memory at address 0x0  
(gdb) po [MySingleton sharedManager]
<Session: 0x1938fa0>

I get the above only when trying to assign. When trying to read the variable is where the crash occurs.

A: 

Likely, whatever kind of object your +sharedManager method returns is not a valid Objective-C object, and trying to access a property of that invalid Objective-C object will cause EXC_BAD_ACCESS. Also, are you sure that EXC_BAD_ACCESS is not occurring within +sharedManager?

dreamlax
It actually started out as an tableview cell object. I hadn't noticed it created that instead of an NSObject. I've since stripped out all of the tableview cell code but it seems something is still referencing that type of class. I'll just create a completely new NSObject class and see if that makes a difference.
4thSpace
The above attempt didn't make any difference.
4thSpace
+1  A: 

Are you ever releasing the singleton? It seems like the instance you are returning is no longer valid. I'd override "release" for the singleton to do nothing, and see if you still have a problem...

Kendall Helmstetter Gelner
Not that I can tell. I've comment out that line in dealloc but that area is never hit by a breakpoint I've set there.
4thSpace
+3  A: 

Given this:

- (void)dealloc {
[someKey dealloc];
[super dealloc];
}

And some of the other code, I'd go out on a limb and say it is likely that there are other problems with the code, the combination of which are leading to the problem you have hinted at. In particular, you should never call -dealloc directly (other than [super dealloc]). If you have that in other parts of your code and it is being executed, it could easily cause the symptom you describe.

If you want a more specific answer, post the backtrace of the crash.

MyApp(51363,0xa0389500) malloc: * mmap(size=2147487744) failed (error code=12) error: can't allocate region
** set a breakpoint in malloc_error_break to debug Current language: auto; currently objective-c

Set the breakpoint as indicated and then re-run the application. Once that error message happens, all bets are off as your app is already hosed. You need the backtrace of when that call is made.

What is happening, though, is that something is asking mmap() to map in 2GB of address space. Could be corruption. Could be bad code.

bbum
Yes - I've discovered it isn't actually the singleton at all. I can assign a string to SomeProperty and it works fine. It is the value coming from a function and then being assigned to SomeProperty that is the issue, which I'll need to work on. Thanks.
4thSpace
A: 

Change this code.

- (void)dealloc {
     [SomeProperty dealloc];
     [super dealloc];
}

Like this

- (void)dealloc {
     [SomeProperty release];
     [super dealloc];
}

DO NOT CALL dealloc method. Except [super dealloc]

tastyone