- (void) processImage:(char *)image; ---char* causes a memory leak? - cocoa

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.

Related

Running out of memory in 'Other Processes' in Usage Comparion Xcode iOS9

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.

How Does NSZombies Really Work?

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.

CDialog memory leaks in VC10

We are upgrading from VC8 to VC10 and have found a number of memory leaks that seem to be CDialog related. The simplest example of this is demonstrated with the following code using a CDialog that just has a number of buttons. In VC10 this leaks, but in VC8 it doesn't:
for (int i = 0; i < 5000; ++i) {
CDialog* dialog = new CDialog;
dialog->Create(IDD_LEAKER, 0);
dialog->DestroyWindow();
delete dialog;
}
Memory usage keeps rising and the example dialog we have with about 30 buttons leaks 10s of Mb.
Note that the above is a test example where we have stripped out all of our dialog handling code, in our real code we have a derived class and use PostNcDestroy().
Oddly neither of the following code examples leak in either VC8 or VC10:
CDialog* dialog = new CDialog;
for (int i = 0; i < 5000; ++i) {
dialog->Create(IDD_LEAKER, 0);
dialog->DestroyWindow();
}
delete dialog;
for (int i = 0; i < 5000; ++i) {
CDialog* dialog = new CDialog;
delete dialog;
}
What are we missing here?
This appears to be down to the way that MFC manages its handle maps:
What is the lifetime of a CWnd obtained from CWnd::FromHandle?
If you wait long enough for your application to become idle, you do get your memory back, i.e. it's not really a leak. However, as you have observed, while Visual C++ 2010 continues to consume more and more memory - until the maps are tidied in OnIdle() - this doesn't appear to happen in Visual C++ 2008.
Debugging an application containing your code does show that there are a lot more objects in the HWND temporary map in the VC 10 version than there are in the VC 9 version.
The handle map code (winhand.cpp) doesn't appear to have changed between the two versions but there's lots of code in MFC that uses it!
Anyway, assuming that you really want to run your program like this - I guess you're running in some kind of automated mode? - then you'll want to force the garbage collection at appropriate intervals. Have a look at this entry on MSDN:
http://msdn.microsoft.com/en-us/library/xt4cxa4e(v=VS.100).aspx
CWinThread::OnIdle() actually calls this to tidy things up:
AfxLockTempMaps();
AfxUnlockTempMaps(/*TRUE*/);

Can anybody use Leaks? (from Instruments)

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.

Do memory deallocation routines touch the block being freed?

Windows HeapFree, msvcrt free: do they cause the memory being freed to be paged-in? I am trying to estimate if not freeing memory at exit would speed up application shutdown significantly.
NOTE: This is a very specific technical question. It's not about whether applications should or should not call free at exit.
If you don't cleanly deallocate all your resources at application shutdown it will make it nigh on impossible to detect if you have any really serious problems - like memory leaks - which would be more of a problem than a slow shut down. If the UI disappears quickly, then the user will think the it has shut down quickly even if it has a lot of work still to do. With UI, perception of speed is more important than actual speed. When the user selects the 'Exit Application' option, the main application window should immediately disappear. It doesn't matter if the application takes a few seconds after that to free up everything an exit gracefully, the user won't notice.
I ran a test for HeapFree. The following program has access violation inside HeapFree at i = 31999:
#include <windows.h>
int main() {
HANDLE heap = GetProcessHeap();
void * bufs[64000];
// populate heap
for (unsigned i = 0; i < _countof(bufs); ++i) {
bufs[i] = HeapAlloc(heap, 0, 4000);
}
// protect a block in the "middle"
DWORD dwOldProtect;
VirtualProtect(
bufs[_countof(bufs) / 2], 4000, PAGE_NOACCESS,
&dwOldProtect);
// free blocks
for (unsigned i = 0; i < _countof(bufs); ++i) {
HeapFree(heap, 0, bufs[i]);
}
}
The stack is
ntdll.dll!_RtlpCoalesceFreeBlocks#16() + 0x12b9 bytes
ntdll.dll!_RtlFreeHeap#12() + 0x91f bytes
shutfree.exe!main() Line 19 C++
So it looks like the answer is "Yes" (this applies to free as well, since it uses HeapFree internally)
I'm almost certain the answer to the speed improvement question would be "yes". Freeing a block may or may not touch the actual block in question, but it will certainly have to update other bookkeeping information in any case. If you have zillions of small objects allocated (it happens), then the effort required to free them all could have a significant impact.
If you can arrange it, you might try setting up your application such that if it knows it's going to quit, save any pending work (configuration, documents, whatever) and exit ungracefully.

Resources