Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


Android NDK mmap llamada roto en dispositivos de 32 bits después de actualizar a Lollipop

Estoy tratando de agarrar 784 MiB de memoria. Sí, sé que es mucho para un teléfono de 32 bits, pero la siguiente llamada funcionó antes de Android 5.0:

mmap(0, 0x31000000, PROT_NONE, MAP_ANON | MAP_SHARED, -1, 0); 

Sin embargo, en tres dispositivos diferentes de diferentes fabricantes, la actualización a Android 5.0 ha roto esto. Supongo que esto es un cambio en la funcionalidad de asignación de memoria en 5.0; Quizás diferentes banderas necesitan ser aprobados?

Aquí está el mensaje de error devuelto en logcat:

 E/libc﹕ mmap fail (pid 9994, tid 10125, size 822083584, flags 0x21, errno 12(Out of memory)) 

  • Cómo usar unix pipes en Android
  • Android LocalServerSocket
  • 3 Solutions collect form web for “Android NDK mmap llamada roto en dispositivos de 32 bits después de actualizar a Lollipop”

    En el punto donde falla el mmap() , abra /proc/self/maps y copie el contenido en un archivo temporario, luego examine el archivo en un editor. Debería ver un montón de entradas como esta:

     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 

    Los números de la izquierda son rangos de direcciones virtuales (inicio / fin) para el proceso. Cuando se crea una nueva asignación, debe ajustarse a la brecha entre las asignaciones.

    En el ejemplo anterior, hay una gran diferencia entre el final de la primera entrada en 0x42c00000 y el inicio de la siguiente en 0x55281000. Eso es aproximadamente 294MB. No hay espacio entre los dos próximos, y sólo un pequeño después de eso.

    Si miras tu mapa de procesos y no encuentras un espacio suficientemente grande para contener tu archivo, tienes tu respuesta. La región entre 0x00000000 y 0xbfffffff está generalmente disponible para las aplicaciones de 32 bits, pero el marco de aplicación utiliza una gran parte de ella. (La parte superior de 1GB está asignada al núcleo.)

    Mi conjetura es que alguna combinación de ASLR y cambios en la memoria virtual de la manera se asigna en Lollipop han llevado a este problema. En el mapa adjunto a esta pregunta similar , la mayor brecha encontrada fue de unos 300 MB. Hay dos regiones "dalvik" grandes, una 768MB (en 12e01000), una 1.2GB (en 84d81000). (Ya que estás ejecutando Lollipop estos son en realidad debido a ART en lugar de Dalvik, pero al parecer la etiqueta pegada.)

    Una posibilidad es que ART tiene mayores requisitos de memoria virtual que Dalvik, y las grandes asignaciones están dificultando que las aplicaciones obtengan grandes regiones mapeadas. También es posible que ART esté sobre-asignando debido a un error. Es posible que desee probar en Marshmallow para ver si algo se arregló.

    Sea cual sea el caso, no se puede crear una asignación si no hay una región de dirección de memoria virtual contigua suficientemente grande como para contenerla. Con el uso del marco de aplicación y las enormes asignaciones ART vistas en la otra pregunta, una asignación de 768 MB no sería posible incluso si el espacio de direcciones virtual no estuviera fragmentado. Necesitará asignar secciones más pequeñas del archivo, y posiblemente des-mapearlas mientras trabaja para hacer espacio.

    Podría valer la pena archivar un error en b.android.com . Adjunte una copia de su archivo de mapa de procesos y especifique la versión de Android y el dispositivo.

    Para obtener un poco más de interpretación / proc / maps salida, vea por ejemplo esta respuesta .

    • Recompila tu biblioteca de aplicaciones para que coincida con lollipop e inténtalo de nuevo.
    • Actualizar su SDK
    • Asegúrese de establecer la plataforma de destino en lollipop en la configuración de la aplicación
    • Reduzca la memoria asignada y compruebe nuevamente

    ¿Has probado la opción LargeHeap?

    En situaciones muy especiales, puede solicitar un tamaño de montón mayor colocando el atributo largeHeap en "true" en la etiqueta de manifiesto. Si lo hace, puede llamar a getLargeMemoryClass () para obtener una estimación del tamaño de montón grande.

    https://developer.android.com/training/articles/memory.html#CheckHowMuchMemory

    Más detalles:

    https://developer.android.com/guide/topics/manifest/application-element.html#largeHeap

    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.