I have an Address interface as this:
#interface AddressCard : NSObject
{
NSString *name;
NSString *email;
}
#property (copy, nonatomic) NSString *name, *email;
-(void) print;
-(void) setName:(NSString *) theName andEmail:(NSString *) theEmail;
-(void) dealloc;
#end
And implementation as:
#import "AddressCard.h"
#implementation AddressCard
#synthesize name, email;
-(void) setName:(NSString *) theName andEmail: (NSString *) theEmail
{
self.name = theName;
self.email = theEmail;
}
-(void) print
{
NSLog (#"==============================");
NSLog(#"| %-21s |", [self.name UTF8String]);
NSLog(#"| %-21s |", [self.email UTF8String]);
NSLog (#"==============================");
}
-(void) dealloc
{
[name release];
[email release];
[super dealloc];
}
#end
When I run it I keep getting an EXEC_BAD_ACCESS during the pool drain. I'm unable to find the cause and any help is appreciated. This is my first step into Objective-C so please bear with me.
thanks
Sunit
Since the error occurs when draining the pool, I might be suspicious that you've already deallocated the object by that point, and the object is over-released (although generally you'll get a "malloc double free" error for this) or perhaps the memory has already been overwritten by something else. I'd suggest running it with zombies enabled, as in this answer — if you have Snow Leopard you can use the Zombies tool in Instruments from Xcode's Run menu. Good luck!
That example looks quite familiar - I just worked through that book myself! The code you've posted above is fine, so the problem must be elsewhere. You might try checking out the author's forum - the source code for each of the steps for that chapter is posted there.
As others have suggested, you might want to look for extra 'release' calls.
Since you are releasing the strings in your dealloc method it would appear that your AddressCard object assumes ownership of the strings but you use this line to define the properites:
#property (copy, nonatomic) NSString *name, *email;
Using copy means that your object is not retaining the strings. Try changing that line to this:
#property (retain, nonatomic) NSString *name, *email;
Using retain means that your object will retain the strings until you release them in your dealloc.
Hopefully that will solve the problem.
Related
I am trying to create non-atomic copy accessors, and I read everywhere that the object should be released at the end. So, if you could help me understand whether I am doing it properly, I would appreciate it. Will the following be correct?
#interface ClassA: NSObject
{
NSString* stringA;
}
#property (nonatomic, copy) NSString* stringA;
#implementation ClassA
#synthesize stringA;
-(void) setStringA: (NSString*) stringInput {
if(stringA != stringInput) {
[stringA release];
stringA = [stringInput copy];
}
}
-(void) dealloc {
[stringA release];
[super dealloc];
}
I am looking for a confirmation whether I need to deallocate stringA in the dealloc method at the end and whether I did it correctly.
Many thanks.
You need to release it, yes. (You don't deallocate things. You release your ownership of them and they may be deallocated as a result.)
Your code is correct.
The rules are that you must release any object you receive from a method whose name begins with "alloc" or "new" or contains "copy". You also must release any object that you retain. Since you call -copy on stringInput, you are responsible for eventually releasing the object you receive from that.
#Ken Thomases is right; your code is correct. A few things, though:
You don't really need to declare the ivar, or synthesize the property, or write your own setter; all this is done for you. So your code (while correct) could be simplified to:
#interface ClassA: NSObject
#property (nonatomic, copy) NSString* stringA;
#end
#implementation ClassA
-(void) dealloc {
[_stringA release];
[super dealloc];
}
#end
Second, if you're using ARC (which I recommend), the code can be simplified even further (by removing the dealloc override completely).
#interface ClassA: NSObject
#property (nonatomic, copy) NSString* stringA;
#end
#implementation ClassA
#end
In this case stringA is released by your class on dealloc, but you don't have to write code to do that; ARC does it for you.
I tried initializing the array :
In .h file
#property (nonatomic, retain) NSArray *accounts;
In .m file :
#synthesize accounts;
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *arrList = [acAccountStore accountsWithAccountType:accountType];
// This returns array
self.accounts = [NSArray arrayWithArray:arrList]; // I tried debug after
// this and it gives me data in debugger.
// Note array List have 3 data in it.
}
Now On button click i call a method:
- (IBAction) ButtonClicked :(id) sender {
NSLog(#" data : %#",[self.accounts objectAtIndex:0]); // Breaks at this point.
// When i tried with debug it gives me (no Objective-C description available)
}
Is the initialization of array correct Or If the code is not right please let me know.
Main concern is when i do debug in viewDidLoad, the self.accounts show me proper values. But after doing the click event its empty and throws EXEC_BAD_ACCESS error.
Thanks for help in advance
hm looks fine. A couple of questions then:
Where are you calling the self.accounts = [NSArray arrayWithArray:arrList];
I assume that the array is being setup before your button is being pressed?
There's no real reason that arc should be clearing out the variable. Have you set a strong reference to it or a weak one? If you're using self. on a variable, you should have :
#property (nonatomic, strong) NSArray *accounts;
or similar to that in the .h file and then
#synthesize accounts;
in the .m file.
If you've got weak instead of strong then ARC may possibly clear the memory but it still shouldn't.
Update:
Create a property for your account store as well. I had this exact issue recently and this fixed it.
#property (nonatomic, strong) ACAccountStore *accountStore;
Original Answer
Because you're using ARC, you need to change your property declaration from
#property (nonatomic, retain) NSArray *accounts;
to:
#property (nonatomic, strong) NSArray *accounts;
With the latest LLVM compiler, you don't need to synthesize properties either. So you can remove #synthesize accounts.
You should always use defensive coding as well, so in your - buttonClicked: method, you should do:
- (IBAction)buttonClicked:(id)sender {
if (self.accounts) {
NSLog(#"data: %#", [self.accounts objectAtIndex:0]);
}
}
This makes sure that the pointer to the array is valid.
You can also check to make sure an item in an array exists before trying to read it by doing:
- (IBAction)buttonClicked:(id)sender {
if (self.accounts.count > 0)
NSLog(#"data: %#", [self.accounts objectAtIndex:0]);
}
}
Happy Friday. Having an interesting time debugging a zombie issue. I have a UITableView that gets its data source from an NSMutableArray loaded with Word objects. (See class below). When the app loads, all is good - the 1st 8 or 9 words display in table view as expected. However when I scroll, I am getting zombies in my Word objects, as evidenced in the debugger output "<Zombie>" as the value for the Word class instance variable values. (See screenshot). This results in a crash.
TableSearch[12440:207] *** -[CFString respondsToSelector:]: message sent to deallocated instance 0x6b1fe70
Here is the Word class
//Word Class
#import "Word.h"
#implementation Word
#synthesize word;
#synthesize definition;
+ (id)wordWith:(NSString *)word Definition:(NSString *)definition
{
Word *newWord = [[[self alloc] init] autorelease];
newWord.word = word;
newWord.definition = definition;
return newWord;
}
- (void)dealloc
{
[word release];
[definition release];
[super dealloc];
}
#end
I am sure this is something dumb but I cannot see where I went wrong.
I ran "Analyze" on Instruments and no issues were reported. After the crash, I ran "malloc_history 12440 0x6b1fe70" and looked at the output but not sure what to look for except for
the class name of the objects that have the zombie, which I did not see.
Any help tracking this down is greatly appreciated.
Thanks!
Are the "word" and "definition" properties of your Word class both defined as "retain"? E.g.
#property (nonatomic, retain) NSString *word;
#property (nonatomic, retain) NSString *definition;
If you've written them as:
#property (nonatomic, assign) NSString *word;
or just
#property (nonatomic) NSString *word;
Then it would account for your crash.
I'm a beginner to XCode.
Below is my code. I want to add an object to a mutablearray. From the debugger window I can see there is one object added to the array "words". I can also see the property "flag" of that object is "NO". The problem is another property "str" is shown as "out of scope".
Can anyone help me with this issue? Thanks a loooooot! Stucked on this one for the whole afternoon.
NSMutableArray * words=[[NSMutableArray alloc] initWithCapacity:numberOfWords];
Word *w=[[Word alloc] init];
[w setStr:#"abc" flag:NO];
[words addObject: w];
[w release];
--
#interface Word : NSObject{
NSString *str;
BOOL flag;
}
-(void) setStr: (NSString *) s flag:(BOOL) b
{
self.str=s;
flag=b;
}
Do you have a property declaration for your string? Are you retaining the string you are setting?
Still AFAIK 'out of scope' does not necessarily mean it was not set or that nothing has been set. Try an NSLog of the value or something. You might find that there is nothing wrong.
Have a look at this question that talks about scope in GDB:
Objective-C: instance variables out of scope in debugger
Your problem is that the string #"abc" is a temporary object who's scope only exists during the [w setStr:#"abc" flag:NO] method call. You should be able to resolve this problem by making str a #property of Word:
#interface Word : NSObject{
NSString *str;
BOOL flag;
}
#property (retain) NSString* str;
#end
And in your implementation file
#implementation Word
#synthesize str;
-(void) setStr: (NSString *) s flag:(BOOL) b
{
self.str=s;
flag=b;
}
#end
I've read many different things about correct memory management for cocoa/objective-c
For instance ive read that any IBOutlets need to be set to 'nil' but something like an NSArray dosnt?
I would also like to know, is it important to call the super method before or after i release/nil everything
To put this memory issue to bed, can some please reply with the 100% correct way you would create a retained property and release it. If your not 100% sure please dont answer.
Here is what im currently doing but something is obviously wrong as i get the very frustrating EXEC_BAD_ACCESS!?! Almost like im releasing something twice?
header.h
#interface MyViewController : UIViewController {
UILabel *aLabel;
NSArray *aArray;
}
#property (nonatomic, retain) IBOutlet UILabel *aLabel;
#property (nonatomic, retain) NSArray *aArray;
method.m
#implementation MyViewController
#synthesize aLabel, aArray;
- (void)dealloc
{
[aLabel release], aLabel = nil;
[aArray release];
[super dealloc];
}
- (void)viewDidUnload
{
self.aLabel = nil; //Not sure about this bad boy???
[super viewDidUnload];
}
#end
In dealloc you have released the aLabel.Means it is not in memory.Again you are write this line ---aLabel=nil;Remove this line.So that it can't gives the Exec_badaccess.This means eventhough you don't have pointer stilll you are trying to access the pointer.