How Does NSZombies Really Work? - xcode

I cannot find any detailed apple documentation on how the NSZombie really functions. I understand that its designed to not actually release objects and just maintain a count of references to catch any extra releases, but how would something like this work:
for(int i = 1; i < 10; i++)
{
NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity: i];
[array release];
}
Since the same variable/object is being allocated/initialized and released in the same application, how would NSZombie's technically handle this? I know that this shouldn't flag any zombies because every alloc has a release, but how would Xcode technically handle re-allocating the same memory with different capacities?

With Zombies, objects don't actually need to be freed[1] -- the object is simply turned into a "Zombie" at some point after the object's retain count reaches 0. When you message a "Zombified" instance, a special error handler is performed.
1) Freeing Zombies is optional. Unless you really need the memory for a long running or memory intensive task, it is a more effective test to not to free the zombies (NSDeallocateZombies = NO)

This question was answered in the comments by Brad Larson.
Quote:
That isn't the same object, or the same memory. You're creating a distinct, new NSMutableArray instance on every pass through that loop. Just because a pointer to each is assigned to array does not make them the same object.
A pointer merely points to a particular location in memory where the object exists. A given object in memory can have multiple pointers to it, or even none (when it is being leaked). NSZombie acts on the object itself, not pointers to it.

Related

ReactiveCocoa: RAC Objects still in memory after all signals complete

I am developing an application on iOS8 based on reactive cocoa. The application mainly does network operations.
I noticed that when all my signals complete and all signal references are nulled, i see a few RAC* objects still alive in the memory when i checked through instruments. Is this intended or is my code leaking memory? When i run the signal, there is an activity surge where i see a lot of RAC objects getting allocated and then it falls back to this state as shown the the below screen capture.
Every subsequent invocation ends in this same state. So i am not very worried about it btw.
http://imgur.com/sCL8Y3p
Thanks,
Those are all shared global instances that RAC uses so it doesn't need to allocate memory for every use of them. I'm sure there's a fancier word for that optimization, but I can't think what it is. For example, check out RACUnit:
+ (RACUnit *)defaultUnit {
static dispatch_once_t onceToken;
static RACUnit *defaultUnit = nil;
dispatch_once(&onceToken, ^{
defaultUnit = [[self alloc] init];
});
return defaultUnit;
}
Since all RACUnits are the same, RAC never bothers to make more than one instance of it. That's all you're seeing.

Memory continuously increase in Instrumentation even with ARC

I am creating an application with ARC enabled and iOS 7 only. My all properties are properly marked as weak and all strong variables are marked as nil where I need it.
When I run my application with Instruments I found that memory allocation is continous increasing. When I go to any screen the memory increases (approximate 2 MB). When I pop that view the memory gets down to only few KBs. I don't know what happening.
while poping a view I am using following:
UPDATE:
[UIView animateWithDuration:0.5 animations:^{
CGRect newFrame = aSideMenu.view.frame;
newFrame.origin = SIDE_MENU_VIEW_ORIGIN_FINAL;
[aSideMenu.view setFrame:newFrame];
} completion:^(BOOL finished) {
[sender setUserInteractionEnabled:YES];
}];
Here I am using aSideMenu in block. aSideMenu is strong variable. Do you think I need to create it's weak reference and use?
__weak id aWeak = aSideMenu;
and use this aWeak instead of aSideMenu?
Also In few block I am using:
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:....nil];
Should I pass weak reference of `dict' too?
I am not sure if this is the reason. Please help me to track the issue. Also let me know if anything else needs to add in this question for better solution.
Thanks
It would be great if you paste your code also. Without code I can just give you some tips.
Like never try to access strong pointer of self in block. Before entering in a block create weak pointer of self.
__weak id weakSelf = self;
and then use weakSelf inside the block.
Better also test your app for unbounded memory growth, where allocated memory never get chance to dealloct, you can take footprints by using Allocation instrument.
Update:
YES because you are calling setter method on strong pointer, it will retain it. You have to make them __weak or __block if they are shared.
https://developer.apple.com/library/ios/documentation/cocoa/conceptual/Blocks/Articles/bxVariables.html#//apple_ref/doc/uid/TP40007502-CH6-SW1
After having some more code, I want to make some thing more clear about the referenceing in block.
Memory issue may arrise when you reference some strong pointer inside block, as block will not let them deallocat, as they have valid reference, this is the major reason of memory issues. For that we have we create a weak pointer by using __weak id so I will not create a retian cycle.
But there is another issue if object have no other vaild reference, It will be deallocated and weak reference will be nil and it can cause a crash.
So good practice is to create a strong reference to weak in side the block and check for the nil.

Do I win memory by explicitly disposing imageView.Image?

I have this code in my app:
var newImage = // ...
if (imageView.Image != null && imageView.Image != newImage)
imageView.Image.Dispose ();
imageView.Image = newImage;
I have three related questions:
Does it immediately release the memory occupied by the previous imageView.Image?
If it does, is there a cleaner solution?
Does this have anything to do with NSAutoreleasePool?
Does it immediately release the memory occupied by the previous imageView.Image?
Not immediately but it should be much faster than waiting for the Garbage Collector.
Calling Dispose will drop the managed reference to the native UIImage. If nothing else (natively) has a reference to the UIImage (RetainCount == 0) then it will be freed (ObjC reference counting).
In your code imageView still has a reference to it until its Image property is set to newImage - which is why I answered not immediately.
If it does, is there a cleaner solution?
Not really. Letting the GC do it's work is cleaner looking - but image can be very big and are worth freeing asap.
Also it's not really worth (and would not be cleaner anyway) adding a local variable to make sure (if no other native reference exists) the image will be freed immediately - it will happen on the next line.
Does this have anything to do with NSAutoreleasePool?
Anything ? well it's memory related in both cases.
Creating images will use (cache) the current NSAutoreleasePool and will, eventually, be drained. If you process a lot of stuff (e.g. a loop) then it's often worth having your own, short-lived, pool to ensure a faster drain.
Some API (well know to require a lot of memory) are decorated with an attribute that will automatically add (btouch) an NSAutoreleasePool - but it's not easy to find out which.
In doubt you better use Apple Instruments to measure...

RetainCount Memory not free'ed

I am stuck with the Cocoa Memory Managagment.
- (IBAction) createPush:(UIButton *)sender {
[create setEnabled:NO];
[release setEnabled:YES];
aLocation = [[Location alloc] init];
// Put some Example Stuff in the Class
aLocation.title = #"Apartment";
aLocation.street = #"Examplestreet 23";
aLocation.zip = #"12345";
aLocation.city = #"Exampletown";
aLocation.http = #"http://google.com";
aLocation.info = #"First Info Text";
aLocation.info2 = #"Second Info Text, not short as the first one";
aLocation.logoPath = #"http://google.de/nopic.jpg";
[aLocation.pictures addObject:#"http://google.de/nopic.jpg"];
[aLocation.pictures addObject:#"http://google.de/nopic.jpg"];
}
- (IBAction) releasePush:(UIButton *)sender {
[release setEnabled:NO];
[create setEnabled:YES];
[aLocation release];
aLocation = nil;
}
This Code works fine if I set or get Variables, but when I call the 'last' release (so the retain count is 0) it dealloc Method of aLocation gets called, but in Instruments Allocations you see that no memory is given back.
Here the Sources of Location:
http://homes.dnsalias.com/sof/Location.m
same Link with a '.h' instead of '.m' for the Header file (sorry its because of the Spaming Rule).
And the whole Project: http://homes.dnsalias.com/sof/Location.zip
Thanks for any help, where is my failure? Dennis
This Code works fine if I set or get
Variables, but when I call the 'last'
release (so the retain count is 0) it
dealloc Method of aLocation gets
called, but in Instruments Allocations
you see that no memory is given back.
What do you mean by "no memory is given back"?
Though oddly named, the memory management of aLocation is correct is the above code (assuming you have released it in dealloc as well).
Why doesn't memory use decrease when a single object is released?
(Paraphrased)
It is likely that your object is relatively tiny and, thus, that single deallocation falls below the ~20K or so needed to show up in Instruments.
If your app is crashing due to memory use issues, looking to a single deallocation is the wrong place to start. The first thing to do is to answer why your app is accreting memory and what is responsible for that growth.
Configure the Allocations instrument to only track live allocations. Then sort by total memory use. That'll show you what type of allocation is consuming the most memory. Start by reducing that.
Heapshot analysis can be very effective in these situations.
Additional Infos here because of maximum number of links and I have'nt the opportunity to post images...
What do you mean by "no memory is given back"?
I will show you the Instruments run, then it should be clear.
Screenshots from Instruments run
If want more Detail klick here for Instruments Run.
Your code is just fine. You are mistaken the output from Instruments. There is no Location object leaking.
For leaks, use the "Leaks" instrument. It won't fire. :-)

EXC_BAD_ACCESS in SQLite on Mac OS

I'm pulling and pushing data from an sqlite database. I use the FMDatabase cocoa wrapper.
I'm pulling and pushing data from multiple threads, but I made sure that more then one transactions never happen at the same time.
I get EXC_BAD_ACCESS after a few hundred call at the database but never at the same time. It's also not memory related (I've tried NSZombies and looked at the memory management of parameters).
Here is the stack and the code :
alt text http://grab.by/1VwY
FMResultSet* result = [db executeQuery:#"select latitude, longitude from cache where name = ?", name];
[result next];
NSString* latitude = [result stringForColumn:#"latitude"];
NSString* longitude = [result stringForColumn:#"longitude"];
I've got no idea, does somebody has one?
Looking through the relevant code in FMDatabase, it seems the sqlite_bind_text() routines uses the SQLITE_STATIC parameter to bind the result NSString's -UTF8String method (which returns an autoreleased pointer).
This means SQLite assumes that the text storage will remain valid for as long as the text remains bound, while the -UTF8String return is only valid for the current autorelease context. If you're using the same FMResultSet over multiple threads or function calls, changing that parameter to SQLITE_TRANSIENT would be much safer.
I'd suggest making that change in every sqlite3_bind_text() call and seeing if it still crashes. If that fixes it, you may want to report it back to the developer as a possible improvement.

Resources