Qué hacer cuando su programa con Allegro no funciona



Contenido




Introducción

Cuando las cosas van mal, a menudo parece buena idea pedir a otras personas ayuda. Afortunadamente para las personas en esta situación, hay muchas personas (tanto desarrolladores de Allegro como usuarios) que están dispuestas a responder preguntas de este tipo, pero hay varias cosas que puede hacer para que este proceso sea más eficiente. Este documento describe algunos pasos que debe tomar cuando tiene un problema con un programa que use Allegro, sugiriendo modos de solucionar el problema usted mismo, y enseñando trucos sobre cuándo y/o cómo pedir ayuda. El seguir estas reglas hará la vida más sencilla para el que le ayude (porque toda la información relevante será presentada de modo conciso y útil), y para el ayudado (porque así será más probable que reciba una respuesta rápida y precisa).



Parte 1 - ¿quién es el culpable?

¿Es un problema de Allegro, o de su código? Para descubrirlo, pruebe ejecutar los programas test de Allegro, en particular test.exe (si tiene problemas con los gráficos), play.exe (problemas de sonido), y el contenido completo del directorio examples (para cualquier cosa que vaya mal). Si no puede reproducir el problema con uno de éstos, entonces probablemente es un fallo suyo, por lo que salte a la parte 3 más abajo.

Si el problema tiene que ver con los modos gráficos, debería conseguir una copia de UniVBE de http://www.scitechsoft.com/. Si esto soluciona el problema, significa que su driver VESA original estaba estropeado de alguna manera. No estoy interesado en oír problemas de este tipo: no hay nada que pueda hacer para solucionarlos, me temo que su única opción es conseguir un driver VESA mejor, obligando al fabricante de tu tarjeta a que solucione los fallos, comprando UniVBE, o escribiendo un driver FreeBE/AF para su tarjeta (mire en http://www.talula.demon.co.uk/freebe/).



Parte 2 - cuando Allegro falla

Si sigue pensado que el problema es de Allegro, mande un email con las características del sistema que contenga una descripción del problema, qué hardware tiene, que servidor DPMI está usando (CWSDPMI, win95, etc), y una lista de los programas con los que pudo reproducir el problema (no sólo es importante saber qué programas fallaron, sino cuales funcionaron, si funcionó alguno).

Si el problema está relacionado con modos gráficos, también debería mandar el resultado que muestran los programas afinfo y vesainfo (la versión reducida es suficiente a no se que se le pida usar explícitamente el parámetro -v: normalmente esos datos extra no son necesarios). Pruebe ejecutar el programa test.exe con varios controladores de Allegro (cualquier controlador nativo que crea que pueda funcionar, y los controladores VESA 2.0 y VESA 1.x), y en varios modos de vídeo, y diga exáctamente qué modos de vídeo con qué profundidades de color causaron problemas. Si no es capaz de ejecutar ninguna resolución SVGA, pruebe test.exe con la opción Autodetect y copie todo el texto que aparece en la mitad de la pantalla.

Si el problema está relacionado con el sonido, pruebe usar el programa setup para configurar manualmente su tarjeta. Quizás deba introducir manualmente los parámetros de su hardware, y si tiene una tarjeta compatible SB, pruebe seleccionar una tarjeta SB más antigua de la que esté autodetectando (SB Pro, SB 2.0 o SB 1.0). Si no consigue que funcione el sonido, su mensaje deberá incluir el nombre y descripción de los controladores de sonido digital y MIDI que estén siendo autodetectados (esta información la enseña el programa play.exe).



Parte 3 - cuando su programa falla

Cuando un programa djgpp falla, normalmente volcará el contenido de la pila que parecerá algo como esto:

      Exiting due to signal SIGSEGV
      General Protection Fault at eip=00001eca
      [corte]

Call frame traceback EIPs: 0x00001eca 0x00001590 0x00001aea

Esta información le indica exactamente dónde ocurrió el fallo. Para que estos datos tengan sentido, debe compilar su programa con información de depurado (usando el parámetro -g), y ejecutar "symify programa.exe" cuando esté viendo el contenido de la pila en pantalla. Eso cambiará los datos a algo parecido a esto:

      Call frame traceback EIPs:
        0x00001eca   _strcpy+14
        0x00001590   _main+56, line 7 of t.c
        0x00001aea   ___crt1_startup+138

En este caso, puede ver que el bloqueo ocurrió en la función strcpy(), que fue llamada en la línea 7 de la función main() del fichero fuente t.c. Ahora sólo tienes que ir a esa línea, mirar lo que esté haciendo allí, y corregirlo :-)

Nota: si el bloqueo ocurre dentro de una función de Allegro, esta información no resultará tan útil. Cuando esto ocurre puede recompilar Allegro con información de depurado (en su directorio Allegro, ejecute "make clean", "set DEBUGMODE=1", y "make install", pero fíjese que debe tener el pack GNU fileutils instalado), y entonces recompile su programa para usar la biblioteca con información de depurado. No olvide reconstruir la versión normal de Allegro (como arriba, pero "set DEBUGMODE=") cuando haya acabado, porque la biblioteca con información de depurado es muy lenta.

Nota 2: incluso cuando el traceback apunta a una función de Allegro, no significa que sea fallo de una rutina de Allegro. Cualquier rutina fallará si le pasa parámetros inválidos, por lo que a no ser que pueda duplicar el problema con uno de los programas de ejemplo de Allegro, debería asumir que es un caso de error de operador y chequear dos veces qué valores le está pasando a la función de Allegro.



Parte 4 - lo que la gente no hace (pero debería)

Uno de los errores más comunes cometidos por los programadores es ignorar el valor de retorno de una función que puede fallar. Tal error normalmente llevará a otros errores inusuales e inesperados, convirtiendo la depuración en una pesadilla. Hay muchas funciones dentro y fuera de Allegro que pueden funcionar o no dependiendo de las circunstancias. Sin embargo le harán saber si funcionaron o no gracias a los valores de retorno documentados.

Siempre que llame a una función que puede fallar (sobre todo set_gfx_mode(), install_sound(), y cualquier cosa que carga datos del disco), es _esencial_ que chequee el valor devuelto por la función, y actúe en consecuencia.

Otra herramienta importante comúnmente olvidada es usar el parámetro -Wall al compilar su código. Cualquier aviso proporcionado por esta opción casi seguramente será un error en su programa, y debería solucionarlo antes de continuar. Un truco útil es compilar también con el parámetro -O, porque obliga a gcc a examinar las acciones de su programa con más detenimiento, activando más avisos útiles. Sin embargo debería desactivar las optimizaciones cuando depure un programa. A pesar de que dan mejores avisos al compilar, posiblemente confundirán las herramientas de depuración que quiera usar.



Parte 5 - pidiendo ayuda

Bueno, así que ha probado todo lo descrito arriba y su programa sigue sin funcionar. No tiene ni idea de qué hacer ahora, por lo que es tiempo de aventurarse en las entrañas de la red, con la esperanza de encontrar algún hombre sabio, adivino u oráculo que tenga la respuesta a su pregunta...

El mejor lugar donde puede preguntar es probablemente la lista de correo de Allegro: más detalles en el fichero readme.txt. Sin embargo, recuerde que esta lista es específica de Allegro. Los problemas relacionados con el lenguaje C o el compilador djgpp pertenecen a otros forums (comp.lang.c y comp.os.msdos.djgpp respectivamente).

Tanto la lista de emails de Allegro como la de djgpp son archivadas, y puede ojear los mensajes desde sus páginas web respectivas. Es muy probable que encuentre una solución a su problema mirando las respuestas a preguntas previas, lo que le evitará hacer la pregunta.

Según la netiqueta usual, se asume que cuando hace una pregunta en cualquier forum de Internet al menos ya ha consultado primero la documentación relevante, leyéndola por completo. Si el problema que tiene merece ser planteado a cientos de personas para que lo resuelvan, seguramente merecerá la pena tomarse unos minutos extra para solucionar el problema usted mismo. Allegro está documentado extensivamente y se considera un prerequisito para hacer una pregunta no sólo el haber leído la documentación, sino también haber examinado los programas de ejemplo.



Parte 6 - aprenda de mis fallos

Qué no hacer, Primera Parte:

      "Mi programa se bloquea. Por favor, dime porqué."

Si, a veces recibo preguntas como ésta :-) A pesar de años de práctica, todavía no soy capaz de leer el pensamiento, por lo que es inútil este tipo de pregunta. Para conseguir ayuda con un problema debe describirlo con suficiente detalle como para que otras personas lo entiendan y puedan reproducirlo: esto normalmente significa mandar parte de su código.


Qué no hacer, Segunda Parte:

      "Tengo un problema con mi programa. Junto con este email mando un
      fichero zip de 500k que contiene diez mil líneas de código y todos los
      gráficos y sonidos necesarios: ¿por favor, puedes depurarlo y decirme
      cual es el problema?"

Después de desperdiciar tiempo y facturas de teléfono para recibir un fichero tan grande, es poco probable que nadie _quiera_ ayudarle, sin olvidar el tiempo que se necesitaría para leer y entender tal enorme cantidad de información. Tiene que aislar una parte más pequeña de código que demuestre el problema: cuanto más corto sea, más probable será que alguien le ayude. Recuerde que está pidiendo a otros que le hagan un favor, por lo que es su responsabilidad hacerles este proceso tan sencillo como puedas.



Parte 7 - escribiendo su petición

La cosa más importante es incluir código que puede ser compilado y comprobado por la persona que lee su mensaje. No mande simplemente todo su programa: extraiga una sección pequeña que incluya las líneas específicas que causan su problema, o reproduzca el problema de forma más simple (a menudo descubrirá que puede encontrar el error usted mismo al hacer una versión simplificada de su programa, por lo que es un buen ejercicio que puede hacer). Este código debería ser un programa pequeño pero completo que puede ser compilado y ejecutado, ya que es muy difícil depurar fragmentos incompletos de código.

Es mejor incluir el código directamente en el texto de su email, porque a la gente le resultará más sencillo leer esto que si tuviesen que extraer el código de un attachment.

Idealmente su ejemplo debería evitar el uso de gráficos externos y ficheros de datos. Está bien incluir un pequeño zip (máx 2k) que contiene información, o si no puede hacerlo, de una descripción de qué ficheros necesita (ej: "pon un fichero .pcx de 32x32 llamado "tile.pcx" en el mismo directorio que el programa). Si no hay modo alguno de simplificar las cosas, debería copiar su programa y sus datos a una página web, y entonces dar la URL del fichero zip en su mensaje.

Debería decir que línea de comando gcc ha usado para crear el programa, y ésta debería incluir el parámetro -Wall.

Describa qué es lo que intenta hacer el programa (puede no ser obvio instantáneamente para otras personas), y también qué es lo que hace realmente cuando lo ejecuta. Normalmente no hace falta indicar el traceback de su programa cuando se bloquea (otras personas pueden duplicarlo por sí mismos siempre y cuando consigan compilar su código), pero debería indicar si aparece este traceback, o se bloquea el programa, o si devuelve resultados incorrectos (si es así, en qué difieren estos de los que esperaba). Es útil marcar su código con comentarios para indicar a qué línea apunta el traceback del programa.

Otra información que pueda añadir puede ser útil. Lo más importante es una descripción corta de su hardware, información relevante de sus controladores, y la versión de Allegro que está usando (por favor no diga "WIP" a secas, sino la fecha exacta si está usando una versión que no sea oficial).



Parte 8 - un modelo de perfección

Como referencia, aquí tiene un ejemplo de lo que yo consideraría un mensaje ideal:


   Estoy teniendo problemas cuando uso los modos de vídeo hicolor en mi
   programa, a pesar de que funcionan bien con los tests de Allegro. Estoy
   usando Allegro 3.0 en un p166, corriendo bajo win95 y usando el driver
   VESA 2.0 de mi tarjeta, que el programa vesainfo describe como "Matrox
   Graphics Inc.".

Este programa debería seleccionar una resolución 640x480 de 16 bits, dibujar un rectángulo azul cerca de la esquina superior izquierda de la pantalla, y entonces esperar la pulsación de una tecla antes de salir, pero simplemente recibo un General Protection Fault cuando lo ejecuto.

Lo compilo usando "gcc -Wall t.c -o t.exe -lalleg", y no obtengo ningún mensaje de error.


--- corta aquí, t.c ---

#include <stdio.h> #include <allegro.h>

void main() { BITMAP *bmp = screen;

install_keyboard();

if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0) { printf("Error seleccionando modo de vídeo\n"); return; }

set_color_depth(16);

/* ¡ se bloquea cuando llama rectfill ! */ rectfill(bmp, 32, 32, 64, 64, 0x001F);

readkey(); }