NSMutableData bugs (iPhone) - iphone

I use NSMutableData objects to store lists of 32 byte structs that represent series data. These series are potentially extended, added, aligned, etc. To save allocation of unnecessary objects I try to extend and append bytes to existing objects rather than allocate new ones.
I noticed some strange behavior in the simulator today: 1) using setLength and increaseByLength didn't always zero all new bytes and 2) use of these objects after modification resulted in crashes. The crashes were all in very different areas but always EXC_BAD_ACCESS. After quite a bit of debugging I ended up allocating new objects for working with via mutableCopy and assigning them to my object attributes when done. That solved all of the issues I was having.
* I am working with these objects in background threads but have wrapped all operations in a synchronized block and have not been able to observe any race conditions on the objects in question.
Has anyone noticed similar oddities?
Thanks.

I haven't received an answer for this so I thought I'd follow up with my solution. I ended up reallocating new NSData / NSMutableData objects as I need them and working with the memory directly before wrapping it in NSData objects.

Related

iPhone how to properly handle Core Foundation references with ARC?

I'm very new to the core foundation programming and would like to know what I'm thinking of doing is correct. I'm using ARC, and am not sure of how it handles non-object references. I need to save a reference to a sample buffer and use it later within the app. Is this possible, or will the sample buffer be deallocated prior to that?
Will using self.sampleBuffer = sampleBuffer_; cause memory leak? Do I need to add a manual call to release after this call?
#property (nonatomic)CMSampleBufferRef sampleBuffer;
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer_ fromConnection:(AVCaptureConnection *)connection
{
//does this cause memory leak?
self.sampleBuffer = sampleBuffer_;
}
It doesn't cause a memory leak. In fact, you're more likely to run into issues from the object being released out from under you, since properties have the assign attribute by default, which means they do not retain (read: own) the assigned object.
If you're holding onto the sample buffer long enough to need it to be a property, you should probably follow the docs and copy the samples to your own buffer instead of holding onto the object handed to your delegate:
If your application is causing samples to be dropped by retaining the
provided CMSampleBuffer objects for too long, but it needs access to
the sample data for a long period of time, consider copying the data
into a new buffer and then releasing the sample buffer (if it was
previously retained) so that the memory it references can be reused.
On the other hand, if you really want to keep a reference to the sample buffer, you can keep everything else as it is and call CFRetain on the object before you assign it to your property (making sure you CFRelease the object that was assigned before). This has equivalent semantics to the strong attribute for Foundation objects.

Nsstring objects changing its data type

I have a certain nsstring property declared in a variable, it is used to do store a text string when i am performing a parsing operation. As this parsing operation happens mulitple times, the Nsstring property changes bizzardly to any random data type and crashing my application. This happens when i try to compare the property with other local variable which is also string. But by the time i compare, the appdelegate variable has already changed its data type, and hence crashes my app.
Any one ever come across such issue? If so, please guide me.
It is a sign that your NSString object has been deallocated so you send a message to a deallocated object. That crashes your application. The datatype changes because after an object is deallocated the memory it was placed in is not correct anymore and may contain a trash. You should use Run with Performance tool -> Leaks tool. It helps a lot in such cases. Please keep in mind that you should enable zombie object detection in settings.

How can I keep memory usage low with a lot of NSStrings, or how do I release NSStrings?

I am working on an app that imports a (very) large csv file into Core Data for catching purposes. The process goes something like this:
Parse the file line-by-line into an NSMutableArray full of NSStrings
After X number of lines, import the array into Core Data (this involves manipulating and in some cases creating new NSStrings)
[NSMutableArray removeAllObjects];
Rinse and repeat
At first glance it looks like the memory should be freed up at the conclusion of each cycle. With large files, however, I am finding that the app crashes after signaling a couple low memory warnings. Running the leaks tool tells me that most of the memory is being used up by CFString objects, which I understand are related to NSString objects (although I don't know how)
I understand that NSString are reused whenever possible, and that they don't act quite the same as other objects where memory is concerned, although I don't understand any of the details. How can I reclaim the memory that my NSString objects are using?
Running the leaks tool tells me that most of the memory is being used up by CFString objects, which I understand are related to NSString objects (although I don't know how)
NSString is actually a class cluster. Although you think you are working with NSStrings, you are almost certainly really working with one of its subclasses. The Cocoa framework chooses which subclass to use depending on circumstances.
CFString is actually not really an NSString at all, it is the pure C string object used by Core Foundation. However, you'll find it is "toll free bridged" to NSString. This means that, to Cocoa, it looks like an NSString. The reason you are seeing lots of CFString usage is because whatever Cocoa API you are using to obtain these strings ultimately performs its work in Core Foundation.
Anyway, all that is irrelevant to your problem except for the fact, that lots of CFStrings more or less means the same as lots of NSStrings. What you need to reduce your memory footprint is nested autorelease pools as Girish has already said. As a first step, modify your algorithm like this:
Create a new autorelease pool.
Parse the file line-by-line into an NSMutableArray full of NSStrings
After X number of lines, import the array into Core Data (this involves manipulating and in some cases creating new NSStrings)
[NSMutableArray removeAllObjects];
drain the autorelease pool
Rinse and repeat (start at 0)
If this doesn't help, or only helps a bit, consider bracketing just the parsing with an autorelease pool.
I am assuming that you don't have memory leak.
If you are using too much autoreleased object this can happen
You try following
Create nested auto release pools --- some time happen that you have some long running loops where auto release object get accumulated. -- so add custom auto release pool to release the auto release object when you required.
Don't use autorelease object in the parsing cycle --- do manual object allocation and release once your work is done.
You can't sure that the memory is consumed by NSStrings only. I suggest you check it thoroughly. Try to go for "Build and Analyze" it will help you to find out leaks.
While using NSString object, instead of going for autoreleased objects like
[NSString stringWithFormat#""];
create your own object and release it as soon as you done with it.
NSString * string = [[NSString alloc]initWithFormat:#""];
//use string object
[string release];
this way you can be sure, that you releasing the string there itself.
or create an Autorelease pool
NSAutoReleasePool * pool = [[NSAutoReleasePool alloc]init];
// do you coding, creation of objects, releasing them, whatever...
[pool drain]; or [pool release];
Also have a look at these memory management tips

Memory about lazy loading

I am reading tutorial book now. When I see an example, I get some confused.
The following codes show a way for lazy loading. Does this motivations array be released after instance deallocated ? or will it occupy this memory block until application terminates.
+ (NSArray *)motivations
{
static NSArray *motivations = nil;
if (!motivations)
{
motivations = [[NSArray alloc] initWithObjects:#"Greed",#"Revenge",#"Bloodlust",#"Nihilism",#"Insanity",nil];
}
return motivations;
}
Edit 1
Thank Georg for a bug.
The example you show has a bug - +arrayWithObjects: returns an autoreleased instance which will be destroyed later. The code was probably intended to be:
motivations = [[NSArray alloc] initWithObjects:#"Greed",#"Revenge",#"Bloodlust",#"Nihilism",#"Insanity",nil];
With that, the array will live until the application terminates.
Because it is a static object, so the system will store the object pointer until the application is terminated. You can use this way to cache by let your pointer point to an object that is not release or autorelease
I recommend to use this approach when you really want to cache some data in memory (usually small or big images data) that requires a lot of CPU or IO processing time to generate. For small data like NSString, you can create new array and return every time you need.
Edit for the comment:
There are 2 things about imageNamed:
1/ You cannot control what is cached and what is not cached by imageNamed:. You may not want to cache an image with big size and only used once, for example.
2/ imageNamed: cannot be used for getting image from Network or folders in the system. It will only load from your bundle
Since this is a class method (indicated by a + instead of a - at the declaration), there is no instance that will be released. (Technically there is an instance of an object of class isa I think (? comment if I'm wrong please, I don't know the inner workings very well) but don't worry about that)
So the class, which exists in memory the whole time the program is running, owns that array. Think of static as about as close as you can get to a class variable, rather than an instance variable. Since the class exists the whole time, the array exists the whole time.
Lazy loading keeps it from being created until the first time that class method is called though, so it isn't wasting memory until you need it.

How can I maintain a global cache of objects? (or a NSMutableSet w/o retaining contents)

I have an iPhone app which deals with a subset of 25,000 places at any given time.
I'd like to maintain a cache of places so that I know that if one part of my application updates a place, every other part that knows about that place sees the update.
My naive implementation is create an NSMutableSet to store references to the cached places.
Methods that find new places will first check the cache and return the cached object or if the place isn't in the cache, they will create a new place object and add it to the cache.
The problem is how do I release objects that are no longer needed?
The NSMutableSet will retain the place so the retainCount will never go to zero and dealloc will never be called.
Is there a kosher method to handle the release scenario? Is there some other pattern for doing this that I'm not aware of.
(and CoreData is not an option at this point, but I understand that it handles this).
Thank you,
On the desktop you can do this with NSPointerSet, on the iPhone it is a bit more difficult.
You can use CoreFoundation to create a non-retaining set if you really want to:
//Default callbacks
CFSetCallBacks callbacks = kCFTypeSetCallBacks;
//Disable retain and release
callbacks.retain = NULL;
callbacks.release = NULL;
cachedPlaces = (NSMutableSet *)CFSetCreateMutable(kCFAllocatorDefault,
0,
&callbacks);
That makes a non-retaining set. Note that you still need to remove the objects from the set when they are released, otherwise you will have stale pointers in your set that will cause you to crash on a deref. So in the objects you are adding to the set you need a dealloc something like this:
- (void)dealloc {
[cachedPlaces removeObject:self];
[super dealloc];
}
This is only really suitable for a purely in memory cache of extant references, if you need to also move stuff to and from the disk then CoreData basically takes care of all of this for you.
You could use NSMutableSet as cache and rely on the fact that any object it contains with a retain count of 1 is only owned by the cache. Thus any object with a retain count of 1 should be removed, this is easily done:
NSPredicate* predicate = [NSPredicate predicateWithFormat:#"retainCount > 1"];
[cachedPlaces filterUsingPredicate:predicate];
Do this on a timer, or whenever a a place is added and/or removed if that is not too often. You could also make the predicate a static to avoid generating anew instance every time.
Use Core Data if you can deploy to iPhoneOS 3.0 or greater, or use SQLite for iPhoneOS 2.x. Either way you'll be able to use a database to store your data, and you'll be able to do queries to get fresh data sets.
As of iOS 4.0, the proper way to do this is to use an NSCache. It can automatically purge objects when the system sends a low-memory warning. You can also set limits on the cache size.
NSCache Class Reference
This question is old, but I recently came across a similar issue. I believe using NSHashTable can fit the requirements of this situation.
NSHashTable works better than NSCache or NSSet because it can hold weak references to your instances, so that once all references are dropped the instance is automatically removed from the NSHashTable thanks to ARC. This works as a kind of 'Just-in-Time' caching method, only retaining objects held elsewhere by strong references.
Considering that you have multiple parts of the application that could be adding references, using the NSHashTable as the Flyweight Pool of the Flyweight Pattern could be useful. The second part of the Flyweight pattern requires a factory, the factory would be responsible for checking for the instance in the pool, adding it to the pool if it's not found, then returning the pooled instance.