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.
Related
My app crashes on devices with 0.5GB memory. However, profiling memory usage in Xcode - it rarely goes above 140MB. I've used instruments to check leaks and there are none that are significant.
However, when I run my app, the memory used by 'Other Processes' is always very high. This is the resting state after launching:
I added a 1 second delay in each cycle of a loop in my code, and discovered that on each loop, the 'other processes' increases memory usage by about 3MB per object, until on 0.5GB devices, it runs out and crashes.
This question suggests that these are other apps using that memory, but I have closed every other app and the usage directly correlates with my looping code.
What could be using memory in other processes, that is actually running in my app? And why is my 'Other Processes' using up so much memory?
To give an idea of what I'm doing, I'm pulling data from Parse, then looping through each of the objects returned and creating an SKNode subclass object from the data. I add this node to an array, (for reference) and to the scene. Here's the code I'm doing on the main thread with the delay added. NB the line:
self drawRelationships:[_batches objectAtIndex:_index] forMini:_playerMini];
Is a BFTask and so asynchronous. And I'm dividing the array into smaller batches so I can see incremental memory usage, as each batch is drawn. If I try to draw the whole lot at once, OOM occurs immediately...
- (void)drawNewRelationships
{
_batches = [NSMutableArray array];
_index = 0;
[_playerMini fetchInBackgroundWithBlock:^(PFObject *object, NSError *error) {
[ParseQuery getNewRelationshipsForMini:_playerMini current:_miniRows.relationshipIds withBlock:^(NSMutableArray *newRelationships) {
_batches = [self batchArrays:3 fromArray:newRelationships];
_index = 0;
[self drawBatches];
}];
}];
}
- (void)drawBatches
{
if ([_batches objectAtIndex:_index]) {
[self drawRelationships:[_batches objectAtIndex:_index] forMini:_playerMini];
_index++;
if (_index < [_batches count]) {
[self performSelector:#selector(drawBatches) withObject:nil afterDelay:1];
}
}
}
The node contains other data, (a couple of arrays, custom object) and I've tried running the app with all that data removed. I've tried running on the main thread and background threads. I've tried using BFTask to do things asynchronously. Everything I've tried ends up with the same behaviour - creating these SKNode objects eats up memory in 'Other Processes', until on low memory devices, it crashes.
It might be worth noting, that this behaviour has only started to occur since iOS9.
Basically, what can be using all this memory in 'other processes' and how can I free it?
Update
I've tried running the Sprite Kit sample app, and even that uses ~550MB in other processes when it launches. Could this be a major Sprite Kit bug?
Well it turned out to be a rather specific issue. The memory allocated to other processes was in fact memory leaking from my app. It occurred when I flattened a node with many children, but didn't nil an NSDictionary that contained references to all the pre-flattened nodes. For some reason, this mem leak didn't show up when profiling.
I also found a very good blog post: http://battleofbrothers.com/sirryan/memory-usage-in-sprite-kit on reducing your app's memory footprint. Worth a read if you're trying to optimise.
I want to provide a solution for those who are not necessarily using SpriteKit, but are facing issues with Other Processes taking up more and more memory - meaning there is a leak. This is the best way I've found to debug leaks in 'Other processes' so far.
Open Instruments, select Activity Monitor
Reproduce the steps in your application, see which process is taking ownership for the leak. For example if it is mediaserverd, you probably have a leak revolving around encoding/decoding or something media related, so things like releasing buffers or releasing the decompression session might not be working as planned.
Now that you have an idea of where to look, open Xcode and use the Debug Memory Graph tool, and look for the potential leaking instances, and you should see all the strong references towards it. For myself working a lot in objective-c++ it turns out to be missing autoreleasepools quite often.
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.
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.
Instrument tells me
NSCFString 16Bytes Foundation -[NSPlaceholderString
My code is like:
BOOL rslt = [self sendLogInfo:[NSString stringWithFormat:#"%#", [nameField text]] andPasword:[NSString stringWithFormat:#"%#",[passField text]]];
But without any alloc method.
Could anyone please tell me what is wrong with the code?
There are two possibilities:
sendLogInfo:, or some other code that you didn't show, retains the string, either directly (by sending it a retain message) or indirectly (by setting it as the value of a strong/retain property).
That code is not the code that produces the string shown in Instruments.
If you hover the mouse over the address (0xblahblah) in the string's row in Instruments, you'll see a button that looks like this: ➲ If you click on that, it will take you to the History for that address, which will list the allocation and every retain, autorelease, and release of that string. You can then examine each event's call stack to see what caused it.
One of those is the cause of the leak: Either an undue retain, or a retain (or the allocation) that needs to be balanced by a release but isn't.
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. :-)