2011-12-14 7 views
8

Nie mogę ustalić, dlaczego iOS kończy moją aplikację (iPad, iOS 4) z powodu użycia pamięci, nawet po zwolnieniu tony pamięci w odpowiedzi na ostrzeżenia o małej ilości pamięci. Na przykład, oto typowy scenariusz wypowiedzenie ze mną zalogowaniu zużycie pamięci co tak często - spojrzeć na „APP” użytkowania, pierwsza wartość KB na każdej linii:Dlaczego iOS przerywa moją aplikację, nawet jeśli zwolniam dużo pamięci w odpowiedzi na ostrzeżenia o pamięci?

... 
2011-12-14 13:25:42.343 Oyster[211:707] Memory usage (KB): app 268256, delta 6472, used 366800/373940 
2011-12-14 13:25:43.292 Oyster[211:707] Memory usage (KB): app 273900, delta 5644, used 372444/381024 
2011-12-14 13:25:44.159 Oyster[211:707] Memory usage (KB): app 282920, delta 9020, used 381464/389116 
2011-12-14 13:25:45.184 Oyster[211:707] Memory usage (KB): app 272140, delta -10780, used 370684/379432 
2011-12-14 13:25:46.109 Oyster[211:707] Memory usage (KB): app 260412, delta -11728, used 358956/365900 
2011-12-14 13:25:48.443 Oyster[211:707] Received memory warning. Level=2 
2011-12-14 13:25:48.454 Oyster[211:707] Memory usage (KB): app 9172, delta -251240, used 107716/112548 
(gdb) 

widać Wykorzystanie aplikacji pamięci wzrasta do dostaje ostrzeżenie o pamięci. Następnie poprawnie reaguję na ostrzeżenie o pamięci i uwalniam pamięć (250 MB!). W tym momencie moja aplikacja zostaje zakończona, a iOS przechodzi do ekranu głównego iPada.

Tutaj wyświetlane są dzienniki "Wykorzystanie pamięci" oznaczone numerem logMemoryUsage() function bazującym na kodzie z this answer.

Do zapisywania używam SDWebImage do buforowania UIImages w pamięci, ale jak pokazano, obsługuje ostrzeżenia pamięci przez opróżnianie jego pamięci podręcznej (raczej duże w tym momencie). Zdaję sobie sprawę, że mogę zmodyfikować pamięć podręczną SDWebImage, aby nie wypełniać całej dostępnej pamięci i tylko czekać na ostrzeżenia o pamięci, ale to rodzi następujące pytanie ...

Dlaczego iOS kończy moją aplikację, mimo że odpowiadam na ostrzeżenia dotyczące pamięci szczęśliwie uwalniając mnóstwo pamięci?

+5

Dołącz dziennik zakończenia. W innym miejscu może wystąpić niepowiązany błąd. – PengOne

+0

Co to jest "dziennik zakończenia" i jak go wyświetlić? –

+0

Włącz debuger. Gdy aplikacja się zawiesza, konsola powinna mieć komunikat o następującej treści: "Aplikacja kończy się z powodu ..." – PengOne

Odpowiedz

1

Bez więcej informacji nie mogę wiedzieć, czy te okoliczności, ale ja często napotkasz pewne kwestie po próbując oczyścić ostrzeżenia pamięci:

  • nieznany referencje okrągłe zapobiec uwolnieniu z pamięci jak się spodziewasz. Użyj instrumentów, aby je wyszukać. Niedawno naprawiłem przypadek, w którym przypadkowo używałem siebie w bloku, powodując zatrzymanie. Zauważyliśmy to, gdy pojawiło się ostrzeżenie o pamięci i nie mogliśmy odzyskać danych z ostrzeżenia, zwalniając ten zasób.
  • Po oczyszczeniu zasobów - lub automatycznym zwolnieniu zasobów - wydano coś, co jest nadal potrzebne. Możesz mieć zero, gdy nie oczekujesz, lub możesz operować na zombie. Sprawdź swoją retencję i porządki, szczególnie nilingi delegatów. Włącz zombie i punkt przerwania wyjątków.

Zazwyczaj najlepszą rozdzielczością jest zapobieganie występowaniu ostrzeżenia o pamięci.

+0

Dzięki za pomoc (wznowione), jednak nie jest to żadna z tych rzeczy: 1) można zobaczyć pamięć aplikacji korzystanie z tej funkcji jest teraz w dół, gdy uwalniam rzeczy, i 2) nie jest to problem z zombie, ponieważ iOS zdecydowanie mnie przerwie (mogę pobrać dzienniki awarii "Moja uwięziona" z mojego iPada). –

11

Jest to ogólna odpowiedź na dobre praktyki dotyczące zarządzania pamięcią itp. Ogólnie rzecz biorąc, brzmi jak pamięć podręczna w pamięci jest po prostu robi się zbyt duża i mimo, że wydaje obiekty w odpowiedzi na ostrzeżenia pamięci, do tego czasu jest za późno.

  1. Ostrzeżenia dotyczące pamięci nie są z natury "złe" i nie można ich uniknąć. Stanowią one normalną część cyklu życia systemu iOS, a użytkownik musi je prawidłowo obsługiwać, zwalniając wszystkie nieistotne dane ze wszystkich obiektów, aby zapewnić, że aplikacja zachowuje się w sposób odpowiedzialny. Nawet jeśli Twoja aplikacja ma niewielki rozmiar, nadal możesz otrzymać ostrzeżenie o b/c inne warunki na danym urządzeniu (np. Inne używane aplikacje itp.). Mam na myśli powiadomienie o uruchomieniu UIApplicationDidReceiveMemoryWarningNotification tutaj. Komunikaty debuggera (np. "Ostrzeżenie o odebranej pamięci, Poziom = 2") są specyficzne dla aplikacji, ale niekoniecznie są powiązane z otrzymywaniem powiadomienia o środowisku wykonawczym.

  2. Niewiele wiem o SDWebCache. Przyjrzałbym się implementacji i upewniłem się, że efektywnie zwalnia pamięć.Na przykład, może użycie @autoreleasepool w odpowiednich miejscach może pomóc w wydajniejszym udostępnianiu obiektów w pętli uruchamiania.

  3. Należy starać się, aby odcisk stopy w aplikacji był maksymalnie ograniczony. dobrze jest używać pamięci podręcznej w pamięci dla danych obrazu, ale ograniczyłbym jej rozmiar. Jeśli rozmiar Twojej aplikacji wynosi> 250 MB, nie jestem zaskoczony, że jest ona przerywana, nawet jeśli obsługujesz ostrzeżenia dotyczące pamięci. Do tego czasu jest już prawdopodobnie za późno.

  4. Twoje mogą mieć inne problemy powodujące/przyczyniające się do rozwiązania umowy. Zgodnie z sugestiami, musisz zrobić więcej debugowania na instrumentach, aby szukać nieszczelności, złego dostępu itp. Zamieszczanie tutaj rejestru awarii byłoby pomocne.

+0

+1 dla numeru 3. Są chwile, kiedy jest już za późno. Ostrzeżenia dotyczące pamięci są dostarczane za pośrednictwem protokołu IPC i występują opóźnienia. 250 MB to DUŻO. Mogę się założyć, że jest "za późno". – ipmcc

+0

@ipmcc, w interesie, czy ostrzeżenia o pamięci są dostarczane przez IPC udokumentowane gdzieś, czy znasz to z publicznego kodu źródłowego lub z innego powodu? –

+0

Możesz zobaczyć za pomocą debuggera (szczegóły wykraczające poza zakres komentarza SO), że ostrzeżenia o pamięci przychodzą w postaci komunikatu mach (np. IPC), który zostaje przekształcony w operację wysyłania głównego wątku, co kończy się uruchomieniem aplikacji. powiadomienie o poziomie. Szczegóły nie są nigdzie udokumentowane. Na dodatek nie ma to znaczenia; Jeśli ostrzeżenia pochodziły z twojego procesu, nadal byłyby asynchroniczne w odniesieniu do zabójstwa, które pochodzi spoza twojego procesu. Wynik netto: jest asynchroniczny niezależnie, a opóźnienie nie będzie możliwe do kontrolowania/rozliczania. – ipmcc

1

Sprawdź kod transformacji obrazu. W projekcie SDWebImage znajduje się kod, który służy do skalowania obrazu, który stosuje pewne techniki transformacji i rotacji na wybranym obrazie. W rzeczywistości nie robi tak wiele, aby zmniejszyć rozmiar, ale czasami powoduje podniesienie ostrzeżenia o pamięci. Skomentuj ten kod i spróbuj zbudować swoją aplikację.

Miałem ten sam problem w mojej aplikacji. Próbowałem skomentować kod transformacji. Problem został rozwiązany. Możesz także spróbować.

1

Ostrzeżenie o poziomie 2 to Urgent. Twoja aplikacja prawdopodobnie otrzyma jedno lub kilka ostrzeżeń poziomu 1 przed otrzymaniem ostrzeżenia poziomu 2, a Ty powinieneś w tym momencie działać.

Z mojego doświadczenia wynika, że ​​kiedy aplikacja otrzymuje ostrzeżenie na poziomie 2, prawie zawsze jest za późno, i tak i tak zostanie zabite.

1

Podczas pracy z dużymi obrazami (4 MB na obraz) może wystąpić ryzyko wyczerpania pamięci bez otrzymywania ostrzeżenia o małej ilości pamięci.

Najlepsze jest, aby zapobiec nadmiernemu wzrostowi zużycia pamięci. Szybkość ładowania obrazów jest taka, że ​​buforowanie jest dobre, ale nie jest konieczne. Znacznie lepiej jest ograniczyć zużycie pamięci, zwalniając pamięć, gdy tylko jej nie używasz.

Życzymy powodzenia i daj nam znać, jeśli znajdziesz coś, co warto udostępnić.

Powiązane problemy