[Guía] Depuraciones errores en scripts y crasheos.

Aprende lo que no sabes de este lenguaje y encuentra herramientas y códigos útiles.

Moderador: Ayudantes

Reglas del Foro
  • Si tu código es corto, no crees un tema nuevo para liberarlo, publica un mensaje en el tema [Funciones] ¡Publica tu código aquí!.
  • Si creas una guía, debes explicar el código claramente. Evita poner la explicación en forma de comentarios dentro del mismo y no olvides utilizar el BBCode correspondiente: [Pawn]Código aquí[/Pawn].
  • No postear códigos sin probar. Publicar códigos con errores (que impidan compilar el script para el cual está destinado) en este apartado es motivo de sanción.
  • Si tu código necesita plugins, includes u otros códigos adicionales para funcionar, debes mencionarlo en el mensaje.
  • Si has utilizado códigos de otros autores, recuerda colocar los créditos correspondientes. (El plagio es motivo de sanción).
  • Si tu aporte es para un GameMode en específico, debes publicar el tema en el apartado "Guías y Aportes para GameModes específicos".
Responder
Avatar de Usuario
gless
Avanzado
Avanzado
Mensajes: 448
Registrado: 22 Oct 2017 04:10
Ubicación: Soy de una casa versátil.
Reputación: 28

25 Nov 2017 21:00

Imagen


¿Qué es la depuración?

La depuración es el proceso de agregar mensajes temporales (o algunas veces permanentes) en el código para dar una representación visual del proceso del guión.


¿Cuándo puede ser útil la depuración?

Los errores en el código pueden hacer que el código se detenga en el error y omita el resto del código, o incluso bloquear o congelar el servidor. Estos errores no son recogidos por el compilador, ya que no son errores cuando se compila el script. Un ejemplo de un error se puede encontrar a continuación.
Puede ser difícil identificar y localizar un error en los grandes scripts, posiblemente demorando meses. Aquí es donde la depuración se vuelve extremadamente útil.



En este ejemplo, el código no causará que el servidor se congele / se bloquee, pero hará que el código se detenga en el error, dejando el resto del código sin procesar.
 Codigo Pawno:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

new pKillStreak[MAX_PLAYERS]; // The player's current killstreak
new pKillStreakReward[MAX_PLAYERS][5]; // 5 killstreaks can be stored per player
 
public OnPlayerDeath(playerid, killerid, reason)
{
    if(killerid != INVALID_PLAYER_ID) 
    {
        new string[128], pName[MAX_PLAYER_NAME], kName[MAX_PLAYER_NAME];
        GetPlayerName(playerid, pName, MAX_PLAYER_NAME);
        GetPlayerName(killerid, kName, MAX_PLAYER_NAME);
        format(string, sizeof(string), "%s (%i) fue asesinado por %s (%i). Razon: %i.", pName, playerid, kName, killerid, reason);
        SendClientMessageToAll(COLOR_DARKRED, string);
 
        pKillStreak[killerid]++; // racha subir..
 
        if(pKillStreak[killerid] == 7) // Dar helicóptero de ataque
        {
            pKillStreakReward[killerid][pKillStreak[killerid]]++; )
            SendClientMessage(killerid, COLOR_GREEN, "[RACHA] - Helicóptero de ataque listo para el despliegue.");
        }
        SetPlayerScore(killerid, GetPlayerScore(killerid)+pKillStreak[killerid]); 
        GivePlayerMoney(killerid, 1000*pKillStreak[killerid]); 
    }
    return 1;
}
  Cantidad de llaves: Abiertas(3)-Cerradas(3) | Lineas Totales: 25
Ahora bien, este no es el código más largo jamás escrito, se mantiene corto para evitar confusiones. Ejecutando ese código, y permitiendo que un jugador obtenga una racha de matanzas (7) se detendrá el código en el error (que se contará a continuación). Debido a eso, el código en la parte inferior que da la puntuación y el efectivo no se ejecutará.

Agregar los mensajes de depuración
Los mensajes de depuración generalmente se agregan usando print () (o printf ()) o mensajes del cliente. Para simplificar, usaremos print (). Para agregar mensajes de depuración, debe colocar mensajes de impresión () cada pocas líneas entre su código y luego ejecutar el código. La última impresión () que aparecerá en server_log le ayudará a localizar el código que está causando el problema mirando el código entre dicha impresión y la siguiente.
Este es el código con la depuración agregada:

 Codigo Pawno:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

new pKillStreak [MAX_PLAYERS];
new pKillStreakReward [MAX_PLAYERS] [5];
 
público OnPlayerDeath (playerid, killerid, razón)
{
    printf ("OnPlayerDeath (% i,% i,% i)", playerid, killerid, razón);
    if (killerid! = INVALID_PLAYER_ID)
    {
        print ("OnPlayerDeath: killerid válido");
        new string[128], pName[MAX_PLAYER_NAME], kName[MAX_PLAYER_NAME];
        GetPlayerName (playerid, pName, MAX_PLAYER_NAME);
        GetPlayerName (killerid, kName, MAX_PLAYER_NAME);
        print ("OnPlayerDeath: nombres almacenados");
        format(string, sizeof(string), "% s (% i) fue asesinado por% s (% i). Razón:% i.", pName, playerid, kName, killerid, razón);
        SendClientMessageToAll (COLOR_DARKRED, cadena);
        print ("OnPlayerDeath: mensaje enviado");
 
        pKillStreak [killerid] ++;
 
        printf ("OnPlayerDeath: pKillStreak ahora es% i", pKillStreak [killerid]);
 
        if (pKillStreak [killerid] == 7) // Helicóptero de ataque
        {
            print ("OnPlayerDeath: 7 killstreak - give attack heli");
            pKillStreakReward [killerid] [pKillStreak [killerid]] ++; // Agrega uno al recuento del killstreak actual (para helicópteros de ataque múltiples almacenados)
            print ("OnPlayerDeath: 7 killstreak - agregó uno a pKillStreakReward para heli de ataque");
            SendClientMessage (killerid, COLOR_GREEN, "[7 KILLSTREAK] - Helicóptero de ataque listo para el despliegue.");
            print ("OnPlayerDeath: Fin del heli de ataque");
        }
        print ("OnPlayerDeath: Dando puntaje ...");
        GivePlayerScore (killerid, pKillStreak [killerid]); // Si tienen 5 killstreak, dales 5 puntos.
        print ("OnPlayerDeath: Puntaje dado. Dar dinero en efectivo ...");
        GivePlayerMoney (killerid, 1000 * pKillStreak [killerid]); // Si tienen un killstreak de 5, dales $ 5000
        print ("OnPlayerDeath: Efectivo entregado");
    }
    print("OnPlayerDeath: Terminado");
    return 1;
}
  Cantidad de llaves: Abiertas(3)-Cerradas(3) | Lineas Totales: 38
Como puede ver, hay funciones de impresión utilizadas en todo el código. Cuando se ejecuta el código, imprimirá los mensajes de depuración en la consola del servidor (y server_log.txt). A continuación, puede localizar el problema.
server_log.txt mostraría esto cuando un jugador obtiene una racha de 7 muertes:

 Codigo Pawno:
1
2
3
4
5
6

[timestamp] OnPlayerDeath(1, 2, 3)
[timestamp] OnPlayerDeath: killerid valid
[timestamp] OnPlayerDeath: names stored
[timestamp] OnPlayerDeath: message sent
[timestamp] OnPlayerDeath: pKillStreak is now 7
[timestamp] OnPlayerDeath: 7 killstreak - give attack heli
  Cantidad de llaves: Abiertas(0)-Cerradas(0) | Lineas Totales: 6
Pero no hay nada después de eso? ¿Que pasó? El script se detuvo. Echemos un vistazo al código que está después de la impresión final ('OnPlayerDeath: 7 killstreak - give attack heli'):
 Codigo Pawno:
1
2
3
4
5
6
7
8

if(pKillStreak[killerid] == 7) // Attack helicopter
        {
            print("OnPlayerDeath: 7 killstreak - give attack heli");
            pKillStreakReward[killerid][pKillStreak[killerid]]++; // <<<<<< THIS IS THE PROBLEM
            print("OnPlayerDeath: 7 killstreak - added one to pKillStreakReward for attack heli");
            SendClientMessage(killerid, COLOR_GREEN, "[7 KILLSTREAK].");
            print("OnPlayerDeath: end of attack heli");
}
  Cantidad de llaves: Abiertas(1)-Cerradas(1) | Lineas Totales: 8
Solo hay una línea de código entre la impresión final que se encontró en server_log.txt y la siguiente, que es
 Codigo Pawno:
1

pKillStreakReward[killerid][pKillStreak[killerid]]++;
  Cantidad de llaves: Abiertas(0)-Cerradas(0) | Lineas Totales: 1
Este es el problema. El pKillStreakReward solo tiene 5 celdas, pero estamos tratando de establecer el 8vo, ya que pKillStreak [killerid] es 7 (los arrays comienzan en 0, entonces 7 es el 8vo). Esto es lo que está sucediendo:
 Codigo Pawno:
1

pKillStreakReward[killerid][7]++;
  Cantidad de llaves: Abiertas(0)-Cerradas(0) | Lineas Totales: 1
¿Que sigue?

Después de haber localizado el problema, debe usar su propio conocimiento para solucionarlo (o solicitar asistencia en los foros de ayuda)..Por ejemplo, pawnoscript.
...


Depuración principal

Si su servidor se crashea a horas aleatorias, tendrá que depurar todo el script. Si bien esto puede parecer desalentador al principio, una vez que sabes qué hacer, realmente no es así. Es causado por una devolución de llamada o un temporizador. Lo que debe hacer es colocar un print() en la primera línea de cada devolución de llamada, así: '

 Codigo Pawno:
1
2
3
4
5
6
7

public OnPlayerDeath(playerid, killerid, reason)
{
    print("DEBUG: OnPlayerDeath");
    // codigo
    // codigo
    return 1;
}
  Cantidad de llaves: Abiertas(1)-Cerradas(1) | Lineas Totales: 7
Luego, cuando el servidor falla, simplemente mira los registros y mira a qué devolución de llamada se llamó en último lugar. Cualquiera que sea la última impresión impresa, es la devolución de llamada que contiene el error. Luego puede depurar esa devolución de llamada aún más, como en el primer ejemplo.
Esto es similar a lo que puede esperar ver en server_log.txt:

 Codigo Pawno:
1
2
3
4
5
6
7

[16:49:54] OnPlayerStreamIn
[16:49:54] OnPlayerStateChange
[16:49:54] OnPlayerRequestClass
[16:49:54] OnPlayerRequestClass
[16:49:54] OnPlayerStateChange
[16:49:54] OnPlayerSpawn
[16:49:54] OnPlayerDeath
  Cantidad de llaves: Abiertas(0)-Cerradas(0) | Lineas Totales: 7
Eso indicó que algún código en OnPlayerDeath causó que el servidor fallara.
En algunos casos, es posible que desee imprimir los parámetros de devolución de llamada, para esto, printf se puede usar así:

 Codigo Pawno:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

public OnPlayerDeath(playerid, killerid, reason)
{
    printf("DEBUG: OnPlayerDeath(%i, %i, %i)", playerid, killerid, reason);
    // code
    // code
    // code
    // code
    // code
    // code
    // code
    // code
    // code
    // code
    return 1;
}
  Cantidad de llaves: Abiertas(1)-Cerradas(1) | Lineas Totales: 15
Bucles infinitos

Otra fuente común de congelaciones de servidores son los bucles infinitos. while () puede causar un ciclo de código infinito e interminable que evitará que el servidor procese más instrucciones. Aquí hay un ejemplo de un ciclo infinito while ():

 Codigo Pawno:
1
2
3
4
5

new var = 5; 
while(var != 3) 
{
    var++;
}
  Cantidad de llaves: Abiertas(1)-Cerradas(1) | Lineas Totales: 5
Esto causará un ciclo infinito, ¡porque la variable nunca se establecerá en 3!

Mensajes del cliente

A lo largo de este tutorial, se han utilizado las funciones print y printf, que imprime texto en la consola / registros del servidor. Esta no es siempre la función más útil para usar, ya que tendría que ir al juego, probar el código y luego minimizar para verificar la consola / registros.
Aquí es donde SendClientMessage podría ser más útil, o quizás incluso textdraws o game-text. Tendrá que usar el formato, a diferencia de printf, donde puede especificar las variables después de la cadena.
Por ejemplo, este código mostrará constantemente una variable para el jugador en OnPlayerUpdate, por lo que puede ver si se cambia accidentalmente:

 Codigo Pawno:
1
2
3
4
5
6
7
8

new pVariable[MAX_PLAYERS];
 
public OnPlayerUpdate(playerid)
{
    new debugStr[32];
    format(debugStr, sizeof(debugStr), "~W~pVariable: ~Y~%i", pVariable[playerid]);
    GameTextForPlayer(playreid, debugStr, 3000, 3); 
}
  Cantidad de llaves: Abiertas(1)-Cerradas(1) | Lineas Totales: 8
O si querías saber cuál era la variable de un jugador cuando pasaron por un punto de control de carrera (checkpoint):
 Codigo Pawno:
1
2
3
4
5
6
7
8
9

new pCP[MAX_PLAYERS];
 
public OnPlayerEnterRaceCheckpoint(playerid, checkpointid)
{
    pCP[playerid]++;
    new debugStr[18];
    format(debugStr, sizeof(debugStr), "Checkpoint: %i", pCP[playerid]);
    return 1;
}
  Cantidad de llaves: Abiertas(1)-Cerradas(1) | Lineas Totales: 9
Productor músical
Programador
Editor Gráfico
Compositor
Cantante
Editor Audiovisual
AMX Booster
Mastering
Webmaster
Scripter
Y odioso, jeje..

Perdí mi facebook, cualquier problema hablarme por privado..

Liberaciones y aportes qué recuerdo.....

[AFK System Pause]: Ir a el sistema
[Pawno y sus funciones] [GUÍA]: Ir a la guía
[Include easyDialog]: Ir a la librería
Tunear vehículo vía comando]: Ir a el sistema
Include foreach: Ir a la librería
Declaraciones ¡RECOMENDADO!: Ir a la guía
Depuraciones y crasheos ¡RECOMENDADO! Ir a la guía
Ordenador policial para OZ: Ir al aporte
Cambiar personaje cómo GTA V: Ir al filterscript
Gamemode Stories of Sa: Ir al gamemode
Mensajes aleatorios: Ir al aporte
Sistema de administración BÁSICO: Ir a el sistema
Modifica tu servidor desde un comando: Ir al aporte
Mapa VC Para GTA.. Ir al aporte

"Pensemos en la modalidad de ayudar al prójimo y no en la competencia.."


-LaredoX
Baneado
Baneado
Mensajes: 37
Registrado: 27 Ago 2017 12:28
Reputación: -1

25 Nov 2017 21:18

me ayudaste con esto hermano, que ostia! +1
Avatar de Usuario
MattHudson
Moderador Global
Moderador Global
Mensajes: 1668
Registrado: 31 Oct 2015 18:16
Ubicación: Argentina, Buenos Aires, San Miguel.
Contactar:
Reputación: 89

25 Nov 2017 21:26

Pensar que una función que envía un mensaje es capaz de tanto -mfr_lol

A día de hoy lo sigo usando a menudo... muy bueno que lo hayas compartido -thumbup
Avatar de Usuario
gless
Avanzado
Avanzado
Mensajes: 448
Registrado: 22 Oct 2017 04:10
Ubicación: Soy de una casa versátil.
Reputación: 28

26 Nov 2017 09:57

Gracias por sus deseos.. -hi
Productor músical
Programador
Editor Gráfico
Compositor
Cantante
Editor Audiovisual
AMX Booster
Mastering
Webmaster
Scripter
Y odioso, jeje..

Perdí mi facebook, cualquier problema hablarme por privado..

Liberaciones y aportes qué recuerdo.....

[AFK System Pause]: Ir a el sistema
[Pawno y sus funciones] [GUÍA]: Ir a la guía
[Include easyDialog]: Ir a la librería
Tunear vehículo vía comando]: Ir a el sistema
Include foreach: Ir a la librería
Declaraciones ¡RECOMENDADO!: Ir a la guía
Depuraciones y crasheos ¡RECOMENDADO! Ir a la guía
Ordenador policial para OZ: Ir al aporte
Cambiar personaje cómo GTA V: Ir al filterscript
Gamemode Stories of Sa: Ir al gamemode
Mensajes aleatorios: Ir al aporte
Sistema de administración BÁSICO: Ir a el sistema
Modifica tu servidor desde un comando: Ir al aporte
Mapa VC Para GTA.. Ir al aporte

"Pensemos en la modalidad de ayudar al prójimo y no en la competencia.."


Responder