W miejscu, gdzie mmap()
zawiedzie, otwartej /proc/self/maps
i skopiować zawartość do pliku tymczasowego, a następnie zbadać plik w edytorze. Powinieneś zobaczyć kilka takich wpisów:
12e01000-42c00000 ---p 00201000 00:04 11639 /dev/ashmem/dalvik-main space (deleted)
55281000-5d500000 r--s 00000000 00:16 61 /storage/sdcard1/blah
5d500000-67e80000 rw-p 00000000 00:00 0 [anon:libc_malloc]
67ea4000-682cc000 r-xp 00000000 b3:17 114807 /system/vendor/lib/libsc-a3xx.so
682cc000-682f4000 r--p 00427000 b3:17 114807 /system/vendor/lib/libsc-a3xx.so
Liczby po lewej stronie to wirtualne zakresy adresów (początek/koniec) dla procesu. Kiedy tworzysz nowe mapowanie, musi ono zmieścić się w luce między mapowaniami.
W powyższym przykładzie istnieje spora, duża luka między końcem pierwszego wpisu 0x42c00000 a początkiem następnego wpisu 0x55281000. To około 294 MB. Między następnymi dwoma nie ma miejsca, a po nim tylko mały.
Jeśli spojrzysz na swoją mapę procesu i nie znajdziesz luki wystarczająco dużej, aby pomieścić plik, masz odpowiedź. Region pomiędzy 0x00000000 i 0xbfffffff jest ogólnie dostępny dla aplikacji 32-bitowych, ale struktura aplikacji wykorzystuje go bardzo dużo. (Pierwszy 1 GB jest zmapowany do jądra.)
Domyślam się, że niektóre kombinacje ASLR i zmiany sposobu przydzielania pamięci wirtualnej w Lollipop doprowadziły do tego problemu. Na mapie dołączonej do this similar question największą znalezioną luką było około 300 MB. Istnieją dwa duże regiony "dalvik", jeden 768MB (przy 12e01000), jeden 1,2GB (przy 84d81000). (Ponieważ używasz Lollipopa, są one raczej wynikiem ART, a nie Dalvik, ale najwyraźniej etykieta utknęła.)
Jedną z możliwości jest to, że ART ma wyższe wymagania pamięci wirtualnej niż Dalvik, a duże przydziały utrudniają aplikacjom uzyskanie dużych mapowanych regionów. Możliwe jest również, że ART ma zbyt dużo alokacji z powodu błędu. Możesz przetestować na Marshmallow, aby sprawdzić, czy coś jest naprawione.
Niezależnie od przypadku nie można utworzyć odwzorowania, jeśli nie ma ciągłego obszaru adresu pamięci wirtualnej wystarczająco dużego, aby go pomieścić. Przy użyciu frameworka aplikacji i olbrzymich alokacji ART widocznych w drugim pytaniu mapowanie 768MB nie byłoby możliwe, nawet gdyby wirtualna przestrzeń adresowa nie była pofragmentowana. Będziesz musiał zmapować mniejsze fragmenty pliku i ewentualnie je odwzorować podczas pracy, aby zrobić miejsce.
Możliwe, że warto zgłosić błąd na b.android.com. Załącz kopię pliku mapy procesu i określ wersję Androida i urządzenia.
Aby uzyskać więcej informacji na temat interpretowania danych wyjściowych/proc/maps, zobacz np. this answer.
Komunikat o błędzie wydaje się dość oczywisty; czy sprawdziłeś, czy dostępna jest wystarczająca ilość pamięci? – Phillip
Nie wiem na temat solidnego sposobu sprawdzenia, ile pamięci jest wolne i dostępne przez kod natywny. Jednak to nie jest naprawdę ta część, której nie rozumiem - nie rozumiem, dlaczego ten sam kod działa na tym samym urządzeniu z Androidem 4.4, a następnie nie działa w wersji 5.0. Jest mało prawdopodobne, że ślad pamięci Androida zwiększył się tak bardzo - wydaje mi się, że jest bardziej prawdopodobne, że wymagana jest jakaś nowa flaga kompilatora lub coś w tym stylu. – sigmabeta
Po prostu użyj 'adb shell free -m' z podłączonego komputera. Jeśli nie masz dostępu do urządzenia, SO ma różne rozwiązania, aby zapytać o dostępną pamięć z C w systemie Linux. (Powinieneś * naprawdę * to zrobić.) – Phillip