I made my own class derived by NSObject, and here is my code:
-(void) parseRow:(NSDictionary*) dictionary {
NSArray* arName = [[dictionary valueForKey:displayname] componentsSeparatedByString:#"+"];
[self setDriverName:[arName objectAtIndex:0]];
[self setDriverSurname:[arName objectAtIndex:1]];
[arName release]; // this give problem!
}
and in my view:
driverStats = [[DriverStats alloc] init];
// driverStats is declared in the header:
DriverStats* driverStats;
#property (nonatomic,retain) DriverStats* driverStats;
[driverStats parseRow:dictionary];
If I add [arName release] in my class, when I exit from parseRow method, I have the EXC_BAD_ACCESS error.... but it's wrong?? I used array and after I released... I think that the error will be if I didn't release the pointer.. or not???
thanks in advance
The problem is easy to solve. Your NSArray *array only have 0 retainCount. Because you use a factory method componentsSeparatedByString:, it returns you an autoreleased array already. So, you don't need to release your array anymore.
Another thing you need to care about is the setDriverName: and setDriverSurname:, make sure you retain/copy the object there otherwise, when the array is released, those objects are also released and EXEC_BAD_ACCESS again
Related
I have an NSMutableArray I'm trying to reload after an async call. The first time it loads like this:
self.sessionProcList = [NSMutableArray arrayWithArray:[result records]];
After the user does some interaction, the same line will be reached to reload the NSMutableArray. This causes the crash
Header file has:
#interface...
NSMutableArray *sessionProcList;
... }
#property (nonatomic, retain) NSMutableArray *sessionProcList;
Say you do:
NSMutableArray *a = [NSMutableArray arrayWithObject: [[NSObject alloc] init]];
NSObject *o = [a objectAtIndex: 0];
[a removeAllObjects];
[o description]; // *BOOM*
The above will [generally -- sometimes not but only by coincidence] crash because o has been deallocated by the time the description method is invoked.
If you have a reference to an object in an array, but have not retained said reference, then said object may be deallocated out from under you when you empty the array.
(And nonatomic vs. atomic is irrelevant.)
If I had to guess, I would say that elements in that array are being referenced from somewhere else. Resetting the array causes the items using the references to crash.
I would check your application for other variables, properties, or UI elements using those variables that have not been release before resetting it.
Because arrayWithArray is a convenience method it gets initialised with an autorelease flag.
You haven't mentioned what the crash / error message is but I am guessing your NSMutableArray is getting released before your second iteraction with it starts.
Try and retain the array for however long you need it with:
self.sessionProcList = [NSMutableArray arrayWithArray:[result records]];
[sessionProcList retain];
And then release it when you're done with it:
[sessionProcList release];
I hope it helps.
Rog
So i have a uiviewcontroller. It has a property of an NSMutableArray with a nonatomic, retain property synthesized.
In the viewDidLoad I init it with the following, and also add a button to the nav bar.
test = [NSDictionary dictionaryWithObjectsAndKeys:
[[SearchField alloc] initWithName:#"Subject" :Text], kSubjectKey,
[[SearchField alloc] initWithName:#"Source publication" :Text], kSourceKey,
[[SearchField alloc] initWithName:#"Keyword" :Text], kKeywordKey,
[[SearchField alloc] initWithName:#"Author" :Text], kAuthorKey,
[[SearchField alloc] initWithName:#"Color" :Bool], kColorKey,
nil ];
NSLog([NSString stringWithFormat:#"lol %d", [test count]]);
The first log, when running through the debugger runs fine. However, I have tied the following code to the button:
-(void)search:(id)sender{
NSLog([NSString stringWithFormat:#"lol %d", [test count]]);
When this code executes the log line crashes with exc bad access. Nothing is happening to the NSDictionary between the viewDidLoad and the button press, so why is this happening? And more importantly, how do I fix it? :)
Cheers
Edit
I thought maybe it was my SearchField class was doing things, so i replaced them with simple strings, the problem still occurs.
You're directly accessing the member variable - you need to go through the accessor - ie:
self.test = [NSDictionary dictionaryWithObje ...
This will make sure your object retains the dictionary.
Make sure test is a class variable, by setting it up as a property of your view controller's header:
#property (nonatomic, retain) NSDictionary *test;
Release it in your view controller's -dealloc method:
[test release], test = nil;
Set its value as follows:
self.test = [NSDictionary dictionaryWithObjectsAndKeys:...];
Access its count property as follows:
NSLog(#"Count: %u", test.count);
Or:
NSLog(#"Count: %u", [test count]);
Note that -count returns an unsigned integer, so you should use %u to format its value.
The dictionary you're creating is autoreleased. You're using a convenience method (dictionaryWithObjectsAndKeys:) which returns a new autoreleased object.
The autoreleased object is being released (and deallocated) some time after its creation, which is why it's crashing later in the program.
You need to retain the returned dictionary, or create a new dictionary using the alloc/init method.
Either way, you need to remember to release the dictionary when you're done with it.
You should read up on the basic memory management rules and conventions for Objective-C.
I have a mutableArray that I fill up with objects. When I try to refill the array, I first use removeAllObjects - which produces a memory leak...
The properties of the object are synthesized, retained and released on dealloc.
The Array is initialized on viewDidLoad like this:
theArray = [[NSMutableArray alloc] initWithCapacity:10];
... and it's retained and synthesized. (#property (nonatomic, retain) NSMutableArray *theArray)
I'm adding the objects in a while-loop like this:
myObject *theObject = [[myObject alloc] init];
theObject.someProperty = #"theprop";
[theArray addObject: theObject];
[theObject release];
then on the next call of the method, I remove all objects like this:
[theArray removeAllObjects];
That's where the leak occurs. If I comment this line out, the leak doesn't appear. So I guess I'm doing something wrong in my object?
Seems like the problem is solved...
a) I didn't realize, that when I use instruments, the app isn't compiled before launch - thus, some of the changes I made were not taking into effect, when using instruments. So now I first build and run after a change and then run it in instruments.
b) thus, I don't really know what solved the problem. But it might be that I had the dealloc-method in my object wrong.
I was using:
[super dealloc];
[myProperty release];
instead of the other way around:
[myProperty release];
[super dealloc];
Thanks for the help, though!
Does myObject have any retained properties? If so, are you setting them to nil in the dealloc message? If not, when it is dealloced it won't release the objects that its properties are set to.
#property (nonatomic, retain) NSMutableArray *filteredListContent;
----
#synthesize filteredListContent;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
NSMutableArray *test = [[NSMutableArray alloc] init];
[test addObject:#"test string"];
[filteredListContent addObjectsFromArray:test];
NSLog(#"%#", test);
NSLog(#"Filtered Array is %#", filteredListContent);
[window makeKeyAndVisible];
}
My Log for test shows 'test string' but 'Filtered list array is (null)'
How do I set the array 'filteredListContent' with the array test...
What am I doing wrong? :-(
Are you creating and initializing filtersListContent anywhere? Your code looks right, that should work.
You should also make sure to release your test variable, you have a memory leak here.
You have to actually create filteredListContent, say with [[NSMutableArray alloc] init]. The error you are getting is that you are calling a method, -addObjectsFromArray:, on an object that is still nil: never created. As such, it just returns nil, and the list is never filtered.
filteredListContent is a pointer to a NSMutableArray, it does not have any memory assigned to it, as a result you cannot call methods on it. The compiler does not generate an error because you are passing a message to nil which is perfectly alright.
Thanx for that.
so I changed the line...
[filteredListContent addObjectsFromArray:test];
to read...
filteredListContent = [NSMutableArray arrayWithArray:test];
This done it. I think I understand it now, though I declared it, I never created it...
Thanx.
I'm getting this error when trying to see the contents of a NSMutableArray:
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x00000021
0x94d5a688 in objc_msgSend ()
ViewController.h:
#interface PeopleViewController : UITableViewController {
NSMutableArray *people;
}
#property (nonatomic, retain) NSMutableArray *people;
ViewController.m:
#implementation PeopleViewController
#synthesize people;
In viewDidLoad:
- (void)viewDidLoad {
[super viewDidLoad];
// initialize our people array with an autoreleased object
people = [NSMutableArray array];
... Populate the people array with Person objects.
}
When I'm at the point where I'm modifying the contents of a cell in the tableview, I'm unable to access the people array in gdb when typing 'po self.people':
Person *person = [[Person alloc] init];
person = [self.people objectAtIndex: indexPath.row]; // <--- 'po self.people' called
cell.textLabel.text = person.personName;
Any ideas why I can't access it?
The line
people = [NSMutableArray array];
returns an autoreleased array that will be released on the next iteration of the current run loop. You should retain that:
people = [[NSMutableArray array] retain];
and of course release it in your dealloc method.
However: Apple engineers have often mentioned in conferences to avoid autoreleased instances like this whenever possible in the iPhone, for performance reasons. Try using alloc/init instead:
people = [[NSMutableArray alloc] initWithCapacity:1];
with the corresponding release in the dealloc method. In this case you don't even need to retain (init returns an instance with a retain count of 1, which is what you need).
And justin's comment is correct: you should do this instead:
Person *person = [people objectAtIndex:indexPath.row];
cell.textLabel.text = person.personName;
and this should work.
is indexPath.row > [people count]?
Also, why are you doing this:
Person *person = [[Person alloc] init]
You're allocating memory, and then pointing to completely different memory.
You can avoid having to fuss with retaining properties by using the self notation to call the accessor and setter methods created by the #synthesize directive.
When you set the people property directly in viewDidLoad it sets the property but does nothing for memory management. However, if you set it with self.people you actually call the synthesized setter method that because of the retain setting of the #property directive will automatically retain the assigned array.
As an aside, I would recommend always using -[NSMutableArray initWithCapacity:] instead of a bare init. It is the actual initializer for the class. You can call it with just '1' if you don't know how big it will be. In the past, I have seen odd problem arise from just using bare init.