I've written a simple program in C and objC with a leak, and I cannot understand Leaks.
here it is:
int main(void)
{
int t = 78;
t = malloc(50);
t = 4;
return 0;
}
Can it show me which variable is the leak, or where it leaks?
Every Leaks tutorial on the internet (all two of them) are bad.
please help?
If you are testing the Leaks instrument with the code you provided, it is no wonder that it can't uncover any problems.
Leaks has a default snapshot interval of 10 seconds. But your program won't even run for 10s.
You are allocating in the scope of the application's entry point. "t" is valid (when not freed) until main exits. So the OS would reclaim the memory anyway.
And foremost: Your code does not contain a leak. It would be a leak if you "loose reference" to t. (e.g. by doing another t = malloc() or assigning t some other variable)
If you want to see Leaks in action, create a default Cocoa Application, add an instance variable "test" to your AppDelegate and put the following code into the implementation.
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
test = malloc(50);
test = malloc(20);
}
I've not used Leaks, but there are plenty of tutorials on the net, starting with Apple's - Apple's developer documentation on the subject, Mobile Orchard and Cocoa is my Girlfriend, which seems to be the best.
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 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...
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. :-)
in my app I'm trying to process an YUV422 image from a webcam. but I'm getting a huge memory leak. below you can see a sample of simplified code of my app. if I disable the "(m1..." line in the function, there is no leak. (but the images are not being processed). I've tried locks, pools, etc but nothing changed. I'm relatively new to cocoa so all these square brackets look funny/scary to me ;-)
is it a problem with using "char"? in my old linux+c++ app there was no problem. but I was using "unsigned char*", no threads, and I have never checked for leaks...
global:
...
char m [640*480];
"main":
...
[NSThread detachNewThreadSelector:#selector(processOutputBuffer) toTarget:self withObject:nil];
...
function1:
- (void)processOutputBuffer {
[NSThread setThreadPriority:0.4];
[lock lock];
...
Ptr outputBufferBaseAddress = (Ptr)CVPixelBufferGetBaseAddress(outputBuffer);
CVPixelBufferLockBaseAddress(outputBuffer, 0);
[self yuv422_to_y8uv8:outputBufferBaseAddress m1:m];
...
}
function2:
- (void) yuv422_to_y8uv8:(char *)image m1:(char *)m1 {
int x,y;
for (y = 0; y < 480; y++)
for (x = 0; x < 640; x++)
{
*(m1 + (640 * y) + (x))=*(image + (640*2 * y) + (x*2)+1);
}
}
if I disable the "*(m1..." line in the function, there is no leak.
Untrue. That's just an assignment. Either there is no leak anyway, or that is not the cause of the leak.
You can use Instruments to look for objects (both plain memory allocations and Cocoa objects) that get leaked, and to diagnose the leaks.
is it a problem with using "char *"?
No. Types do not cause leaks. Incorrect memory management causes leaks.
in my old linux+c++ app there was no problem. but I was using "unsigned char*", no threads, and I have never checked for leaks...
It's possible that you introduced the leak when adding threads, or when adding Cocoa code. It's equally possible that the leak was always there and you never saw it before. Only when you find the problem with Instruments or another tool will you know for sure.
You might also try running the Clang Static Analyzer. It can detect some code patterns that cause leaks, among other things.
A lame answer... I know. But in case no better answer comes to you. You can always put the function in a C file and make it plain c.
Might even be nice to see if it solves the leak. If not, then the problem lies somewhere else.
I'm writing the memory manager for an application, as part of a team of twenty-odd coders. We're running out of memory quota and we need to be able to see what's going on, since we only appear to be using about 700Mb. I need to be able to report where it's all going - fragmentation etc. Any ideas?
You can use existing memory debugging tools for this, I found Memory Validator 1 quite useful, it is able to track both API level (heap, new...) and OS level (Virtual Memory) allocations and show virtual memory maps.
The other option which I also found very usefull is to be able to dump a map of the whole virtual space based on VirtualQuery function. My code for this looks like this:
void PrintVMMap()
{
size_t start = 0;
// TODO: make portable - not compatible with /3GB, 64b OS or 64b app
size_t end = 1U<<31; // map 32b user space only - kernel space not accessible
SYSTEM_INFO si;
GetSystemInfo(&si);
size_t pageSize = si.dwPageSize;
size_t longestFreeApp = 0;
int index=0;
for (size_t addr = start; addr<end; )
{
MEMORY_BASIC_INFORMATION buffer;
SIZE_T retSize = VirtualQuery((void *)addr,&buffer,sizeof(buffer));
if (retSize==sizeof(buffer) && buffer.RegionSize>0)
{
// dump information about this region
printf(.... some buffer information here ....);
// track longest feee region - usefull fragmentation indicator
if (buffer.State&MEM_FREE)
{
if (buffer.RegionSize>longestFreeApp) longestFreeApp = buffer.RegionSize;
}
addr += buffer.RegionSize;
index+= buffer.RegionSize/pageSize;
}
else
{
// always proceed
addr += pageSize;
index++;
}
}
printf("Longest free VM region: %d",longestFreeApp);
}
You can also find out information about the heaps in a process with Heap32ListFirst/Heap32ListNext, and about loaded modules with Module32First/Module32Next, from the Tool Help API.
'Tool Help' originated on Windows 9x. The original process information API on Windows NT was PSAPI, which offers functions which partially (but not completely) overlap with Tool Help.
Our (huge) application (a Win32 game) started throwing "Not enough quota" exceptions recently, and I was charged with finding out where all the memory was going. It is not a trivial job - this question and this one were my first attempts at finding out. Heap behaviour is unexpected, and accurately tracking how much quota you've used and how much is available has so far proved impossible. In fact, it's not particularly useful information anyway - "quota" and "somewhere to put things" are subtly and annoyingly different concepts. The accepted answer is as good as it gets, although enumerating heaps and modules is also handy. I used DebugDiag from MS to view the true horror of the situation, and understand how hard it is to actually thoroughly track everything.