SIGSEGV en Canvas.clipPath en el segundo clipPath
Tengo un ASUS Nexus 7 con Android 4.2.2 Mi aplicación está generando un SIGSEGV en sk_malloc_flags al ejecutar el siguiente código:
static Picture createDrawing() { Path firstPath = new Path(); firstPath.moveTo(3058, 12365); firstPath.lineTo(8499, 3038); firstPath.lineTo(9494, 3619); firstPath.lineTo(4053, 12946); firstPath.close(); Path fourthPath = new Path(); fourthPath.moveTo(3065, 12332); fourthPath.lineTo(4053, 12926); fourthPath.lineTo(9615, 3669); fourthPath.lineTo(8628, 3075); fourthPath.close(); Picture picture = new Picture(); Canvas canvas = picture.beginRecording(12240, 15840); canvas.clipPath(firstPath); canvas.clipPath(fourthPath); << SIGSEGV occurs here picture.endRecording(); return picture; }
El SIGSEGV se informa de la siguiente manera:
- Cómo averiguar la razón de un SIGSEGV en Android
- ¿Cómo puedo capturar SIGSEGV (error de segmentación) y obtener un seguimiento de pila bajo JNI en Android?
- GC y onTouch causan un error de señal fatal 11 (SIGSEGV) en la aplicación que utiliza ffmpeg a través de ndk
- SIGNAL 11 SIGSEGV bloqueo de Android
- La aplicación se bloquea (a veces) con señal fatal 11 (SIGSEGV), código 1
I/DEBUG ( 124): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr deadbaad I/DEBUG ( 124): r0 00000027 r1 deadbaad r2 4017f258 r3 00000000 I/DEBUG ( 124): r4 00000000 r5 bed72434 r6 bed72508 r7 1be773bc I/DEBUG ( 124): r8 1be730f9 r9 000042c3 sl 00000001 fp 67185010 I/DEBUG ( 124): ip 40443f3c sp bed72430 lr 401522f9 pc 4014e992 cpsr 60000030 ... I/DEBUG ( 124): backtrace: I/DEBUG ( 124): #00 pc 0001a992 /system/lib/libc.so I/DEBUG ( 124): #01 pc 00018070 /system/lib/libc.so (abort+4) I/DEBUG ( 124): #02 pc 000be4b4 /system/lib/libskia.so (sk_malloc_flags(unsigned int, unsigned int)+28) I/DEBUG ( 124): #03 pc 0008afc0 /system/lib/libskia.so (SkRegion::op(SkRegion const&, SkRegion const&, SkRegion::Op)+1716) I/DEBUG ( 124): #04 pc 00089448 /system/lib/libskia.so (SkRasterClip::op(SkRasterClip const&, SkRegion::Op)+128)
Obviamente, he simplificado el código a la anterior, la aplicación completa utiliza transformaciones, etc basado en algunos datos de entrada para generar los valores. ¿Son algunas sugerencias sobre cómo solucionar esto sin implementar mi propio código para el recorte en el caso general?
- Android Fatal señal 11 (SIGSEGV) en 0x636f7d89 (código = 1). ¿Cómo se puede localizar?
- Xamarin Android Crash en Inicio "Got a SIGSEGV"
- Extraño dibujo de choque en lienzo en Android 4.0.3. A / libc: Señal fatal 11 (SIGSEGV)
- No se puede depurar I / DEBUG (187): señal 11 (SIGSEGV), código 1 (SEGV_MAPERR), error addr 00000004
- Señal 11 (SIGSEGV), código 1 (SEGV_MAPERR)
Esto se parece a un caso de esquina mal destinado para la manipulación de clipPath
.
canvas.clipPath(fourthPath);
Causa una fusión con firstPath
anterior, sin embargo, dado que éstas son complejas (no rectangulares), el sistema de formas intenta dibujarlas como scanlines
y fusionarlas posteriormente. Para hacer esta fusión, necesita asignar un poco de memoria, pero como se puede ver en SkRegion.cpp , va para el heuristic worst case
.
static int compute_worst_case_count(int a_count, int b_count) { int a_intervals = count_to_intervals(a_count); int b_intervals = count_to_intervals(b_count); // Our heuristic worst case is ai * (bi + 1) + bi * (ai + 1) int intervals = 2 * a_intervals * b_intervals + a_intervals + b_intervals; // convert back to number of RunType values return intervals_to_count(intervals); }
Para sus caminos este worst_case_count
se acerca a 2GB y obtendrá un aborto debido a no obtener esa gran memoria de malloc
.
No pude ver ninguna forma de salir de él utilizando diferentes parámetros. Cualquier cosa que evite la fusión de clipPath
debe ayudar, como llamar a clipPath con Region.Op.REPLACE
. Region.Op.INTERSECT
debería fallar.
Me concentraría en evitar llamar a clipPath con una ruta compleja en la parte superior de una ruta compleja.
Si se adapta a su caso de uso, puede utilizar el mismo objeto Path
para establecer canvas.clipPath()
. Por ejemplo:
Picture picture = new Picture(); Canvas canvas = picture.beginRecording(12240, 15840); Path path = new Path(); path.moveTo(3058, 12365); path.lineTo(8499, 3038); path.lineTo(9494, 3619); path.lineTo(4053, 12946); path.close(); canvas.clipPath(path); // do stuff with canvas path.moveTo(3065, 12332); path.lineTo(4053, 12926); path.lineTo(9615, 3669); path.lineTo(8628, 3075); path.close(); canvas.clipPath(path, Region.Op.REPLACE); // do more stuff with canvas picture.endRecording(); return picture;
Dado que la path
contiene dibujos anteriores, puede continuar actualizándola. Si esto no es aplicable a su caso, usted necesita hacer esos números más pequeños o dividir sus regiones complejas en más pequeñas para evitar que la worst case heuristic
sea demasiado grande.
Ok, déjame poner esto en una respuesta, ya que parece bastante lógico para mí:
Para ver si el problema viene de las llamadas clipPath(Path)
a clipPath(Path)
, intente quitar la llamada al principio o poner canvas.clipPath(fourthPath, Region.Op.REPLACE);
En el lugar de canvas.clipPath(fourthPath);
Y ver si esa es la causa.
Otra cosa en la que puedo pensar es si las dibujas por separado:
Picture picture = new Picture(); Canvas canvas = picture.beginRecording(12240, 15840); canvas.clipPath(firstPath); picture.endRecording(); canvas = picture.beginRecording(12240, 15840); canvas.clipPath(fourthPath); picture.endRecording();
Parece que Canvas.clipPath () no es compatible con aceleración de hardware, por lo menos doc dice que: http://developer.android.com/guide/topics/graphics/hardware-accel.html#unsupported
La única solución que me viene a la mente es desactivar la aceleración de hardware.
Puedes hacerlo en:
-
Nivel de aplicación
<application android:hardwareAccelerated="true" ...>
En manifiesto -
Nivel de actividad
android:hardwareAccelerated="false"
Para la actividad en manifiesto -
Nivel de visualización
view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
Para una vista individual en tiempo de ejecución
Docs:
http://developer.android.com/guide/topics/graphics/hardware-accel.html#controlling