В приложении iPhone происходит утечка памяти; Инструменты и Clang не могут найти утечку

Я разработал программу для iPhone, которая является своего рода программой для обработки изображений:

Пользователь получает UIImagePickerController и выбирает изображение. Затем программа выполняет некоторые тяжелые вычисления в новом потоке (для обеспечения отзывчивости приложения). У потока, конечно же, есть собственный пул автозапуска. Когда расчет завершен, разделенный поток сигнализирует основному потоку, что результат может быть представлен. Приложение создает новый контроллер представления, помещает его в контроллер навигации.

Короче:

  1. UIImagePickerController
  2. новый поток (пул автозапуска) выполняет тяжелые вычисления с данными изображения
  3. сигнал к основному потоку, что это сделано
  4. основной поток создает контроллер представления и помещает его в контроллер навигации
  5. контроллер представления представляет результат изображения

Моя программа работает хорошо, но если я отключу контроллер вида сверху контроллера навигации, нажав кнопку «Назад» и повторю весь процесс несколько раз, мое приложение выйдет из строя. Но только на устройстве! Инструменты не могут найти никаких утечек (за исключением некоторых незначительных, за которые я не чувствую ответственности: создание потока, NSCFString; всего около 10 КБ). Даже статический анализатор Clang говорит мне, что с моим кодом вроде все в порядке.

Я знаю, что класс UIImage может кэшировать изображения, и объекты, возвращаемые из удобных методов, освобождаются только тогда, когда их пул автозапуска истощается. Но большую часть времени я работаю с CGImageRef и использую методы alloc, init и release UIImage, чтобы как можно скорее освободить память.

В настоящее время я не знаю, как изолировать проблему. Как вы подойдете к этой проблеме?

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**

person Norbert    schedule 26.09.2009    source источник
comment
Вы выполняете все вызовы CGImage в основном потоке?   -  person 5ound    schedule 02.07.2010


Ответы (3)


Вы ловите и обрабатываете предупреждения памяти? Ваш код может просто использовать слишком много памяти. Попробуйте использовать метод -(void)didReceiveMemoryWarning в контроллере представления, чтобы узнать, вызывается ли он.

Такое поведение будет соответствовать тому, что вы видите, поскольку устройство iPhone имеет очень ограниченный объем памяти, но симулятор iPhone ограничен только оперативной памятью вашего компьютера.

person Jeff Kelley    schedule 26.09.2009
comment
Да, я отвечаю на это предупреждение. Моя реализация освобождает всю ненужную в настоящее время память, такую ​​как контроллеры представления. - person Norbert; 26.09.2009
comment
но вы также называете суперреализацию? Кроме того, правильно ли вы обрабатываете viewDidUnload? - person Joshua Weinberg; 02.07.2010

Я закомментировал некоторые строки и построил несколько тяжелых циклов for вокруг определенных фрагментов кода, чтобы изолировать и найти проблему. Оказалось, что я удалил строку в меньшем методе, который должен был очиститься после вычисления:

CGImageRelease(result);

Таким образом, при создании нового изображения старый результат просочился.

Интересно, почему Clang или Instuments не нашли эту утечку. Но спасибо за вашу помощь!

person Norbert    schedule 27.09.2009

Под «утечкой» вы имеете в виду инструмент «Утечка»? Это может не «видеть» память, потребляемую вашими вызовами CG, как утечки, потому что они маллокированы ...

Вам во много раз лучше использовать ObjectAlloc и посмотреть, какая память там удерживается в течение короткого периода времени (перетащите временную шкалу с удерживаемой опцией, чтобы увидеть небольшой отрезок времени).

person Kendall Helmstetter Gelner    schedule 27.09.2009
comment
Ах, приятно знать! Я использовал ObjectAlloc, но в целом живые байты всегда были меньше 2 МБ. - person Norbert; 28.09.2009