开发者

Question about pointers in Objective-C

In a global.h file I declare

dataManager *IdataManager;

Then later when the program initializes I allocate and initialize the variable, and use it in several different views as a means of accessing a set of data that gets downloaded when the app starts up.

Recently I noticed when I pull up one of my views, close it, and then open it again, I get a crash when trying to access the global IdataManager.

I finally came to the conclusion that it's contents were being released somehow by the view being de-initialized. I looked at the only place I was using the variable:

CCandidate *currentCandidate = [IdataManager CurrentCandidate];

So I changed this to say:

CCandidate *currentCandidate = [[IdataManager CurrentCandidate] retain];

I wasn't sure how the retain keyword worked, but it sounded like if the view really was releasing my data, I should specify in the creation of this pointer that it should be retained.

This fixed the crashing, but I don't really understand why this happened. Does objective-c just always release pointers you created when you dealloc it's owner? I was under the impression I was simply storing a memory address and giving it the name currentCandidate.

CCandidate.h:

#import <Foundation/Foundation.h>


@interface CCandidate : NSObject {
 int ID;
 NSString* FName;
 NSString* MName;
 NSString* LName;
 NSString* FullName;
 NSString* DOB;
 NSString* Occupation;
 NSString* Employer;
 NSString* Phone;
 NSString* Fax;
 NSString* Email;
 NSString* Website;
 NSString* Party;
 NSString* TwitterUName;
 NSString* TwitterHashTag;
 NSString* Biography;
 NSString* BiographyLink;
 NSString* co;
 NSString* cb;
 NSString* uo;
 NSString* ub;

}

- (id) init;

@property (nonatomic, assign) int ID;
@property (nonatomic, retain) NSString* FName;
@property (nonatomic, retain) NSString* MName;
@property (nonatomic, retain) NSString* LName;
@property (nonatomic, retain) NSString* FullName;
@property (nonatomic, retain) NSString* DOB;
@property (nonatomic, retain) NSString* Occupation;
@property (nonatomic, retain) NSString* Employer;
@property (nonatomic, retain) NSString* Phone;
@property (nonatomic, retain) NSString* Fax;
@property (nonatomic, retain) NSString* Email;
@property (nonatomic, retain) NSString* Website;
@property (nonatomic, retain) NSString* Party;
@property (nonatomic, retain) NSString* TwitterUName;
@property (nonatomic, retain) NSString* TwitterHashTag;
@property (nonatomic, retain) NSString* Biography;
@property (nonatomic, retain) NSString* BiographyLink;
@property (nonatomic, retain) NSString* co;
@property (nonatomic, retain) NSString* cb;
@property (nonatomic, retain) NSString* uo;
@property (nona开发者_高级运维tomic, retain) NSString* ub;

@end

CCandidate.m:

#import "CCandidate.h"


@implementation CCandidate
@synthesize ID;
@synthesize FName;
@synthesize MName;
@synthesize LName;
@synthesize FullName;
@synthesize DOB;
@synthesize Occupation;
@synthesize Employer;
@synthesize Phone;
@synthesize Fax;
@synthesize Email;
@synthesize Website;
@synthesize Party;
@synthesize TwitterUName;
@synthesize TwitterHashTag;
@synthesize Biography;
@synthesize BiographyLink;
@synthesize co;
@synthesize cb;
@synthesize uo;
@synthesize ub;

-(id) init {
 self = [super init];
 ID = -1;
 return self;
}

@end


You probably release currentCandidate at the end of your method, or on deallocating your view. Since you didn't retain the currentCandidate object, you shouldn' release it either!

Scan your code for something of the sorts: [currentCandidate release]

Make sure you read up on memory management. Its pretty important.

http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html


You write that it crashes when you access IdataManager. This is not true. You're program crashes when you try to access the CurrentCandidate object you received using the following line:

// read about naming methods here: http://cocoadevcentral.com/articles/000082.php
CCandidate *currentCandidate = [IdataManager CurrentCandidate];

I suspect you're releasing currentCandidate somewhere you shouldn't. It works the first time because you get back an autoreleased object (You musn't release those yourself!).

This is how it goes:

First time:

  1. Get autoreleased currentCandidate.
    retain count == 2

  2. <your code>

  3. [currentCandidate release] or [currentCandidate autorelease]
    retain count == 1

  4. <your code>

  5. All autoreleased objects get released.
    retain count == 0

  6. currentCandidate gets deallocated.

Second time:

  1. Get autoreleased currentCandidate. This is an invalid object that has already been deallocated. -> CRASH.

If [IdataManager CurrentCandidate] doesn't return an autoreleased object as it should but instead just the pointer to the member of IdataManager, the code crashes later when accessing currentCandidate.

The fact that adding retain helps proves that you're releasing currentCandidate somewhere. Either directly, via autorelease or though some other algorithm. All classes from Apple only release objects that they've retained earlier on. Somewhere in your code there's an unbalanced retain/release.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜