Приложението за iPhone изтича памет; Instruments и Clang не могат да открият теча

Разработих програма за iPhone, която е нещо като програма за манипулиране на изображения:

Потребителят получава UIImagePickerController и избира изображение. След това програмата прави някои тежки изчисления в нова нишка (за отзивчивост на приложението). Нишката има, разбира се, собствен пул за автоматично освобождаване. Когато изчислението е направено, отделената нишка сигнализира на основната нишка, че резултатът може да бъде представен. Приложението създава нов контролер за изглед и го поставя в контролера за навигация.

Накратко:

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

Програмата ми работи добре, но ако отхвърля контролера за изглед отгоре на навигационния контролер, като докосна бутона за връщане назад и повторя целия процес няколко пъти, приложението ми се срива. Но само на устройството! Инструментите не могат да намерят никакви течове (с изключение на някои незначителни, за които не се чувствам отговорен: създаване на нишка, NSCFString; общо около 10 kB). Дори статичният анализатор на Clang ми казва, че кодът ми изглежда е наред.

Знам, че класът UIImage може да кешира изображения и обекти, върнати от удобни методи, се освобождават само когато техният пул за автоматично освобождаване се изтощи. Но през повечето време работя с CGImageRef и използвам методите на UIImage' alloc, init & release, за да освободя памет възможно най-скоро.

В момента не знам как да изолирам проблема. Как бихте подходили към този проблем?

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 е ограничен само от RAM паметта във вашия компютър.

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 MB. - person Norbert; 28.09.2009