views:

509

answers:

3

Hi,

i've developed an iPhone program which is kind of an image manipulation program:

The user get an UIImagePickerController and selects an image. Then the program does some heavy calculating in a new thread (for responsiveness of the application). The thread has, of course, its own autorelease pool. When calculation is done, the seperated thread signals the main thread that the result can be presented. The app creates a new view controller, pushes it onto the navigation controller.

In short:

  1. UIImagePickerController
  2. new thread (autorelease pool) does some heavy calculation with image data
  3. signal to main thread that it's done
  4. main thread creates view controller and pushes it onto navigation controller
  5. view controller presents image result

My program works well, but if I dismiss the navigation controller's top view controller by tapping on the back button and repeat the whole process several times, my app crashes. But only on the device! Instruments cannot find any leaks (except for some minor ones which I don't feel responsible for: thread creation, NSCFString; overall about 10 kB). Even Clang static analyzer tells me that my code seems to be all right.

I know that the UIImage class can cache images and objects returned from convenience methods get freed only whet their autorelease pool gets drained. But most of the time I work with CGImageRef and I use UIImage' alloc, init & release methods to free memory as soon as possible.

Currently, I don't know how to isolate the problem. How would you approach this problem?

Crash Log:

Incident Identifier: F4C202C9-1338-48FC-80AD-46248E6C7154
CrashReporter Key:   bb6f526d8b9bb680f25ea8e93bb071566ccf1776
OS Version:          iPhone OS 3.1.1 (7C145)
Date:                2009-09-26 14:18:57 +0200

Free pages:        372
Wired pages:       7754
Purgeable pages:   0
Largest process:   _MY_APP_

Processes
         Name                 UUID                    Count resident pages
        _MY_APP_ <032690e5a9b396058418d183480a9ab3>   17766 (jettisoned) (active)
     debugserver <ec29691560aa0e2994f82f822181bffd>     107
    syslog_relay <21e13fa2b777218bdb93982e23fb65d3>      62
notification_pro <8a7725017106a28b545fd13ed58bf98c>      64
notification_pro <8a7725017106a28b545fd13ed58bf98c>      64
            afcd <98b45027fbb1350977bf1ca313dee527>      65
    mediaserverd <eb8fe997a752407bea573cd3adf568d3>     319
            ptpd <b17af9cf6c4ad16a557d6377378e8a1e>     142
         syslogd <ec8a5bc4483638539fa1266363dee8b8>      68
        BTServer <1bb74831f93b1d07c48fb46cc31c15da>     119
            apsd <a639ba83e666cc1d539223923ce59581>     165
         notifyd <2ed3a1166da84d8d8868e64d549cae9d>     101
      CommCenter <f4239480a623fb1c35fa6c725f75b166>     161
     SpringBoard <8919df8091fdfab94d9ae05f513c0ce5>    2681 (active)
      accessoryd <b66bcf6e77c3ee740c6a017f54226200>      90
         configd <41e9d763e71dc0eda19b0afec1daee1d>     275
       fairplayd <cdce5393153c3d69d23c05de1d492bd4>     108
   mDNSResponder <f3ef7a6b24d4f203ed147f476385ec53>     103
       lockdownd <6543492543ad16ff0707a46e512944ff>     297
         launchd <73ce695fee09fc37dd70b1378af1c818>      71

**End**
A: 

Are you catching and handling memory warnings? Your code could just be using too much memory. Try using the -(void)didReceiveMemoryWarning method in a view controller to see if it's getting called.

This behavior would be consistent with what you're seeing, since the iPhone device has a very limited amount of memory, but the iPhone simulator is limited only by the RAM in your computer.

Jeff Kelley
Yes, I'm responding to this warning. My implementation releases all currently unnecessary memory, such as view controllers.
Norbert
but are you also calling the "super" implementation?Also, are you handling viewDidUnload properly?
Joshua Weinberg
A: 

I commented out some lines and build some heavy for-loops around certain code fragments to isolate and find the problem. It turned out that I have deleted a line in a smaller method which was supposed to clear up after the computation:

CGImageRelease(result);

So when generating a new image, the old result got leaked.

I wonder why Clang or Instuments didn't find this leak. But thanks for your help!

Norbert
A: 

By "Leak", do you mean the instruments Leak tool? That may not "see" the memory consumed by your CG calls as leaks because they are malloced...

You are many times better off using ObjectAlloc, and looking at what memory is being held onto there in a short time period (drag across the timeline with option held down to see a small region of time).

Kendall Helmstetter Gelner
Ah, good to know!I've used ObjectAlloc, but overall living Bytes were always under 2MB.
Norbert