martes, 31 de enero de 2017

Bug de gedit "pygi-argument.c:1583"

Si desea simplemente saber como solucionar su problema, dirigirse a la sección de posibles soluciones, en caso de querer conocer un poco de como me quitó horas de sueño este bug, puede continuar leyendo.

Hace algún tiempo que trabajo en Ubuntu, y me gusta usar el editor gedit para realizar mis scripts. Por azares de la vida, y cuestiones de configuraciones, al editar documentos para compilar con Latex,  estos parecen seguir sus propios caprichos y no se dejan editar, pues al intentar abrir tales documentos, el programa se cierra abruptamente.

Revisando el todo poderoso google hallé que el bug no solo era mio, pues al buscar usando el mensaje de error que es:

ERROR:../../gi/pygi-argument.c:1583:_pygi_argument_to_object: code should not be reached

Hallé varios resultados, y uno de ellos me llamó la atención, en ese momento supuse que tenía algo que ver con la codificación del texto, y me fijé en algo curioso, que los documentos que tenían problemas eran guardados con la codificación de windows para el carácter de fin de linea, aunque el capricho seguía, luego de ahondar más, el problema era en algunos de esos archivos. Luego de hacer mejor la tarea, y recordando algunos tips de la programación de scripts, recordé aquelo de "Algunos compiladores no reconocen bien la última línea del código", efectivamente, por ese motivo (bien o mal fundado) acostumbro poner varias lineas en blanco al final de los scripts.

Cuando parecía que había dado con el error, solo fue una falsa esperanza. Revisando a lupa de detalle, reduje mi archivo a un documento con letras 'a', y al final un símbolo '¿', se guardó el archivo que contenía justo 8193 bytes, en formato UTF-8, y el error desaparecía si quitaba byte (8192 bytes). Después de varias pruebas entendí que la codificación de dicho carácter genera el error, pero con la particularidad de que si o solo si se halla en una posición de memoria precisa, el byte 8191 (0x1fff) y 8192(0x2000), pues en UTF-8 '¿' se escribe con dos bytes (0xC2 0xBF), de tal suerte que si antes de tal carácter se suprime o agrega algo, el error desaparecía.

Luego, analicé el archivo del foro desde el cual partieron mis sospechas, ese archivo si que es corto (7 bytes), en hexadecimal corresponde a:

20 67 73 69 C4 0D 0A

Si somos "expertos" (sarcasmo) con formatos de textos, podemos deducir que el fin de linea es 0D 0A (CR+LF), si se cambia por el estilo manejado en Linux, el problema persiste:

20 67 73 69 C4 0A

Incluso quitando todo el fin de línea el problema continua. Así que a este punto, leyendo un poco sobre UTF-8, entendí que el problema puede ser el siguiente:

Al tratar de leer el archivo, no sabe si esta en formato ASCII, UTF-8, ISO-88-59-15 (1 byte por carácter), pareciera que lo primero que asume es que es UTF8, y de razón, por que Ubuntu trae por defecto esta codificación, con la mala suerte que genera un fatal error cuando un archivo no está codificado realmente así, pues  como en el caso mostrado al tener C4 contiene los bits 110xxxxx que hace que espere un segundo byte en UTF-8, y como no existe ese byte, supongo que al tratar de acceder a la posición de memoria fuera de la memoria reservada ocurre el fallo.

Posibles modos de solución

  1. La mas simple, puede ser abrir el documento con otro programa y guardar el documento cambiando el formato de nueva linea (\n), por ejemplo si está en el formato Linux (LF), usar el formato  de Windows (CR+LF), o viceversa y cruzar los dedos.
  2. Agregar algún carácter al comienzo del documento, con esto las posiciones donde hay caracteres no ASCII cambian y podría ya no existir el error.
  3. Abrir el documento con otro programa, por ejemplo el notepad con el que viene Wine, copiar al portapeles el contenido, abrir un nuevo documento con gedit, pegar la información y guardar con el formato que comúnmente trabaje más.
  4. Usar otro editor de archivos de texto =(.

Posibles situaciones que generan el error

  1. Usar archivos que contienen caracteres especiales que no se han creado desde el inicio en el mismo directorio (traídos o copiados de algún lado diferente).
  2. Al editar un documento, abrir otros documentos que presentan el error, o que simplemente están en formatos de codificación diferente, es decir puede estar abierto un archivo en ISO-88-59-15, y luego se abre otro archivo con formato UTF-8, esto puede hacer que aparezca el bug, si algún carácter que no sea ASCII esta en una posición de memoria en particular.

Conclusión sobre el origen del mal

Mi hipótesis es que Gedit no gestiona bien el reconocimiento de diferentes formatos de codificación del texto, lo cual en ciertos casos provoca que trate de acceder a posiciones de memoria no reservadas para terminar de leer los caracteres. Me da la impresión que el tipo de formato de un documento en especial, siempre que se haya gestionado bien su formato, se guara tal información por aparte del archivo en si, por ello el mismo archivo con el error, puede en tales casos donde Gedit tiene un soporte del formato adecuado, abre el documento sin problemas, y por ejemplo al copiar ese mismo archivo a otro directorio, ya puede generar inconvenientes, por ello mismo una recomendación para evitar el error es trabajar con el documento sin cambiarlo de directorio, ni tampoco abrir otros documentos que estén en otro formato de codificación de caracteres.

lunes, 17 de octubre de 2016

Herramienta para agrupar textos semejantes

Tanto tiempo sin publicar nada, pero bueno, hoy les traigo una herramienta que realicé con googlescript para poder agrupar textos semejantes.

La base del algoritmo de comparación de textos está en el algoritmo de distancia de Levenshtein, al cual le hice algunos ajustes, el importante y a saber, la distancia ya no es un número entero, si no un valor normalizado de 0 a 1, donde 0 indica que la distancia es cero, y 1 que son totalmente diferentes. La distancia es el criterio para agrupar los textos parecidos que se hallan en una hoja cálculo, es excelente para procesar información que se recibe a través de formularios en google.

A continuación les dejo un video donde se explica su modo de uso, previo deben crear una copia del documento con los scripts de la herramienta.


Como bonus también está la herramienta para pasar información entre diferentes listas de información.