Memory leak advice needed

Discussion in 'Mac Programming' started by Grumpy Mike, Aug 23, 2010.

  1. Grumpy Mike macrumors newbie

    Joined:
    Jan 25, 2010
    #1
    I have written an application for combining images into 3D anagliphs and image pairs. This worked fine until Snow Leopard came along, now it crashes on the second time a file is saved. I've put all sorts of printing to see where it falls over. I get this:-
    Message recieved on consol:-

    Program received signal: “EXC_BAD_ACCESS”.
    sharedlibrary apply-load-rules all

    is received when executing :-

    NSLog(@"about to get images from interface");
    rImageData = [view valueForOutputKey:mad:"Right_Image_out"];
    NSLog(@"one");
    lImageData = [view valueForOutputKey:mad:"Left_Image_out"];
    NSLog(@"two");
    // it gets this far
    imageData = [view valueForOutputKey:mad:"FinalImage"];
    // never gets here on the second time through
    NSLog(@"Just got images from interface");

    If someone could help point me where I am going wrong I would much appreciate it. I am much more of a hardware type of person so I am a bit lost here.

    The source code is available at:-
    http://www.thebox.myzen.co.uk/Site/3D_Slide_Maker_2.zip

    Thanks
     
  2. robvas macrumors 68020

    Joined:
    Mar 29, 2009
    Location:
    USA
  3. subsonix macrumors 68040

    Joined:
    Feb 2, 2008
    #3
    Have you tried it in instruments, or perhaps gdb?
     
  4. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #4
    I'm not so sure this is caused by a memory leak.

    A leak is when memory is allocated but never freed. The eventual result is that all available memory is consumed, until nothing is left to allocate. The program runs out of memory and may crash.

    A more likely cause is an over-release. Or perhaps a "dangling" object pointer that is still being used, despite the object being freed.

    To find over-releases or incorrectly held references to dead objects, the NSZombieEnabled flag is useful.

    As I recently posted in another thread:
    Run your program with NSZombieEnabled.
    http://cocoadev.com/index.pl?NSZombieEnabled

    Doing this will cause any dealloc'ed object to become a zombie, rather than having its memory freed. Then you load your shotgun and start shooting the zombies in the head.

    Another useful link:
    http://www.cocoabuilder.com/archive/cocoa/87251-how-do-debug-an-autorelease-crash.html
    Find the word "handy".​
     
  5. Grumpy Mike thread starter macrumors newbie

    Joined:
    Jan 25, 2010
    #5
    Thanks for the advice so far.
    I have run it with instruments and saw an ever increasing amount of memory allocated. Although to be honest I can't make much sense of what I am seeing and can't relate what it tells me to the activity of my program.

    It appears not to be a zombie problem but it gave me the idea of looking at the reverse.
    The first time I run
    imageData = [view valueForOutputKey:mad:"FinalImage"];
    a print of the right side of the statement gives me:-
    two <NSImage 0x1214f00 Size={1200, 1600} Reps=(
    "QCNSBitmapImageRep 0x1221160 Size={1200, 1600} ColorSpace=Generic HDR Profile colorspace BPS=8 BPP=32 Pixels=1200x1600 Alpha=YES Planar=NO Format=1 CurrentBacking=<NSMutableData: 0x12216f0>"
    but the second time it is run I get:-
    -[NSCFNumber setBitmap:rowBytes:bounds:format:]: unrecognized selector sent to instance 0x1032f80

    So it appears that:-
    [view valueForOutputKey:mad:"FinalImage"]
    is getting mashed. This is not happening for the other output keys before it. The "FinalImage", as well as all the other output keys are published outputs from a Quartz composer sketch so I am at a loss to know why it is getting mashed like this.
    Any further insights?
    Thanks
     
  6. knightlie macrumors 6502a

    Joined:
    Feb 18, 2008
    #6
    I'm a relative noob to Obj-C, but that error right there implies that you (or something else) are sending the setBitMap:rowBytes:bounds:format: message to an object that doesn't respond to it.

    Do you have that call in your source code? A BAD_ACCESS often means you're sending messages to, or trying to read from, a nil pointer - one that hasn't been initialised or has been released.
     
  7. jared_kipe macrumors 68030

    jared_kipe

    Joined:
    Dec 8, 2003
    Location:
    Seattle
    #7
    The error is in the method -savePair:

    Code:
    		[self saveImage:2 fn:f];
    		[f release];
    
    Needs to become...

    Code:
    		[self saveImage:2 fn:f];
    		[f autorelease];
    
    The reason should be apparent. I have verified the bug without the change, and was unable to reproduce it after the change. Though reading the method -saveImage:fn: indicates that this fix may be at least partially unsafe. Due to the fact that -saveImage:fn: does not retain "f" and then uses it. However autoreleased objects don't go away very regularly so it should be safe enough.

    EDIT: I have notified the original author of the software.
     
  8. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #8
    You probably have more than one bug. Ever-increasing memory often signifies a memory leak (something not deallocated). An unrecognized message often signifies an over-release.

    However, if you're running with zombies enabled, then ever-increasing memory is guaranteed to happen. That's because every object that receives dealloc is actually converted into an NSZombie instance. Its memory is never freed.

    I don't think you fully understand all the consequences of using zombies.


    This is specifically telling you that an object of the class NSCFNumber was sent a message setBitmap:rowBytes:bounds:format:. The way this usually happens is you release the object that does respond to that message, but you've kept the pointer in a variable somewhere. That pointer is later reallocated at some point to an instance of NSCFNumber. Zombies should find this.

    Zombies are not a problem to be solved. Zombies are a tool you use to find problems like over-release or dangling references. You are the zombie-master.

    When zombies are enabled, the over-released object becomes a zombie instead of being released. When it's sent a message (i.e. you send a message to an over-released object or a dangling reference), you see a log message about sending messages to a zombie. It identifies the message and origin.

    The purpose of zombies is to give predictable behavior to dangling pointers. Otherwise released object don't necessarily remain objects.

    And you should probably engage the debugger.


    EDIT:
    I should also point out that "over-released" can also mean under-retained. This arises when you assign an unowned object pointer to a variable, but neglect to call retain on it.

    There are many many methods that return objects which are NOT owned by the caller of that method, and whose lifetime may be limited by an autorelease pool. If those unowned objects will be needed for a longer time than the active function, they should be retained. They must also be subsequently released when ownership is no longer needed.

    http://developer.apple.com/mac/libr...al/MemoryMgmt/Articles/mmObjectOwnership.html
     
  9. jared_kipe macrumors 68030

    jared_kipe

    Joined:
    Dec 8, 2003
    Location:
    Seattle
    #9
    Actually this is a little wrong. In objective-C, unlike say Java, you do not need to make sure a pointer is not null/nil to message it.

    Code:
    //Obj-C
    someObject = [otherObject returnsSomeObject];
    [someObject someMethod];
    
    Code:
    //Java
    someObject = otherObject.returnsSomeObject();
    if (someObject != null) {
        someObject.someMethod();
    }
    
    The later is probably one of the most frequently typed Java code chunks ever.

    Secondly, the reason that NSCFNumber doesn't respond to -setBitMap:... should be apparent. However the reason that this object got passed this message at all when it is not in the code is simply because the old object that should have been there was no longer there because it got released before it was no longer used.
     
  10. jared_kipe macrumors 68030

    jared_kipe

    Joined:
    Dec 8, 2003
    Location:
    Seattle
    #10
    Turns out there is more than just this. I have looked through many of the methods, several of them make the same memory management type errors.

    There are also deprecated functions, which I replaced with modern equivalents, same issue.

    After stepping through and modifying a bit of code it does appear to be
    [view valueForOutputKey:mad:"FinalImage"]

    I've never used quartz composer, so I would have to assume there is something wrong inside there. Or there is something odd about the use of your QCView*

    Personally I tried stopping and starting rendering, and removing some suspicious loose ends inside the QC file, (again I don't know anything about quartz composer, but I removed both giant blue panels and it doesn't seem to have changed the way it behaves. Nothing has fixed it.
     
  11. jared_kipe macrumors 68030

    jared_kipe

    Joined:
    Dec 8, 2003
    Location:
    Seattle
    #11
    You may be correct in this, after looking, practically every instance variable is set with auto released objects and a lot of them are fed into QCView *view, which may be retaining them, but maybe not. It does appear that there are a lot of general memory management problems going on.
     

Share This Page