5

Mam grupę awarii w natywnym kodzie, które są rzadkie, ale występują konsekwentnie w przetwarzaniu SEGV_MAPERR lub SEGV_ACCERR. Te awarie są prawie zawsze zgłaszane przez Crashlytics z bardzo niską pamięcią RAM (zazwyczaj 1-5%). "Normalne" awarie (tj. Te, które zostały zdebugowane) nie mają żadnego wzorca w pamięci RAM.Czy niska pamięć może powodować błędy skrępowania w natywnym kodzie?

Czy to możliwe, że awarie są spowodowane niskim poziomem pamięci? Jaki byłby mechanizm tego? Czy istnieje sposób na stwierdzenie, czy są to awarie związane z niską pamięcią, czy błędy programowania (błędne użycie wskaźników itp.)? W wielu przypadkach zdarza się awaria w bibliotece, której nie można debugować i nie mogę replikować awarii na moich urządzeniach.

Oto niektóre z tych wypadków wyciągnąć z konsoli programisty, ponieważ daje trochę więcej szczegółów niż Crashlytics w ślad w następujących przypadkach:

********** Crash dump: ********** 
Build fingerprint: 'htc/a32eul_metropcs_us/htc_a32eul:5.1/LMY47O/637541.3:user/release-keys' 
pid: 10902, tid: 10989, name: .xxx.xxxx >>> com.xxx.xxxxx <<< 
signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 0x97f78000 
Stack frame #00 pc 0004cd80 /data/app/xxx.xxx.xxxxx-1/lib/arm/libxxx.so: Routine xxxxxMixerInterleavedFloatOutput at libgcc2.c:? 

********** Crash dump: ********** 
Build fingerprint: 'Xiaomi/land/land:6.0.1/MMB29M/V8.1.1.0.MALMIDI:user/release-keys' 
pid: 2661, tid: 2746, name: .xxx.xxxx >>> com.xxx.xxxx <<< 
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 
Stack frame #00 pc 00016954 /system/lib/libc.so (__memcpy_base+36) 
Stack frame #01 pc 0000b14c /data/app/com.xxx.xxxx-2/lib/arm/libswresample-2.so: Routine ?? 
??:0 
+1

'SEG_MAPERR' zwykle jest wynikiem działania złego wskaźnika (dereferencing a NULL, użycie wiszącego wskaźnika, wypadnięcie z końca tablicy, eetc). 'SEG_ACCERR' ma tendencję do kojarzenia z próbą uzyskania dostępu do pamięci bez uprawnień (np. Zapis na stronie tylko do odczytu). O ile niska pamięć może zwiększyć prawdopodobieństwo wystąpienia takich zdarzeń, przyczyną źródłową będą złe operacje wskaźnika w kodzie. – Peter

Odpowiedz

6

Istnieją dwie główne możliwości:

  1. Sam niski stan pamięci nie będzie w jakiś sposób powodować uszkodzenia w działającej aplikacji. Może się zdarzyć, że gdy aplikacja zażąda alokacji dodatkowej pamięci, żądanie alokacji pamięci nie powiedzie się. Jest to dobrze zdefiniowany warunek pamięci. Udokumentowano, że odpowiednie wywołania systemowe mogą zawieść w przydzielaniu pamięci. Ale często zdarza się, że aplikacja nie jest poprawnie zakodowana, aby sprawdzić nieudane żądanie alokacji pamięci, i powodują awarię z tego powodu. W takim przypadku nie jest prawdą, że warunek niskiej ilości pamięci jest odpowiedzialny za uszkodzenie aplikacji, jest to błąd aplikacji.

  2. Jądro Linuksa overcommits the available memory. W wyniku tego jest możliwe, że jądro nie będzie miało innego wyboru, jak wybrać proces, który ma zostać zabity, gdy wyczerpana zostanie cała dostępna pamięć RAM.

Jednak w przypadku zabójcy OOM kopanie w, wybrane ofiary zakończona SIGKILL. A SEGFAULT oznacza błąd aplikacji.

+0

Czy jesteś pewien, że # 2 na Androida. http://stackoverflow.com/questions/2567683/why-does-my-program-ocasally-segfault-when-out-of-memory-rather-than-throwin wydaje się mówić, że nadmierne zobowiązania mogą powodować SEGFAULT. –

+0

http://arstechnica.com/civis/viewtopic.php?f=20&t=1240341 ​​ –

+0

To "SIGKILL" [zgodnie z tą pierwszą odpowiedzią] (http://stackoverflow.com/questions/6132333/how-to- wykrywanie-pamięci-segfaults). To ma sens. Celem jest pozbycie się tego procesu. "SIGSEGV" można przechwycić, a jeśli zostanie złapany, sygnał zostanie po prostu ponownie wyświetlony, gdy funkcja obsługi sygnału powróci. "SIGKILL" nie daje się złapać i gwarantuje się, że pozbędzie się procesu, co jest tutaj celem. –