Pregunta

Así que estoy haciendo un juego de la serpiente con telepuertos y los ratones de costumbre. Tenía un bucle se ejecuta de esta manera:

while(snake.alive() && miceEaten < micePerLevel)
{
    displayInfo(lives, score, level, micePerLevel - miceEaten);
    //some code
    if(miceEaten())
    {
        //update score...
    }
    //more stuff...
}

El problema con el código anterior era que displayInfo es llamado antes de la puntuación se actualiza, por lo que después de comer un ratón, el usuario tiene que esperar hasta que el bucle se ejecuta de nuevo para ver su puntuación actualiza. Así que me mudé de que una línea de código a la parte inferior de la función:

while(snake.alive() && miceEaten < micePerLevel)
{
    //some code
    if(miceEaten())
    {
        //update score...
    }
    //more stuff...
    displayInfo(lives, score, level, micePerLevel - miceEaten);
}

y telepuertos dejan de funcionar! El programa se bloquea cada vez que la serpiente llega a un telepuerto. Y displayInfo utiliza el siguiente código:

stringstream s;
s << "LEVEL " << left << setw(12) << level << "LIVES: " << setw(12) << lives << "MICE LEFT: " << setw(12) << miceLeft
    << "SCORE: " << setw(13) << score;
printLine(0, s.str(), WHITEONBLUE);

Cuando printLine sólo tiene un color_set, mvprintw y refresh(). Nada que ver con Telepuertos. Raro.

Así que se fue a la función de serpiente, donde la serpiente obtiene su próxima ubicación de un telepuerto:

    body.push_back(teleports[overlap(next)]->teleportFrom(dir)); //next is a Location object

Cuando teleports[overlap(next)]->teleportFrom(dir) devuelve la ubicación de la serpiente es para ser teletransportado a. En un intento para ver por qué estaba fallando (? Quizá Teleport regresaba alguna fuera de la pantalla de ubicación), he añadido los siguientes 3 líneas antes de la línea anterior:

    Location l = teleports[overlap(next)]->teleportFrom(dir);
    mvprintw(1, 0, "(%i, %i)", l.x, l.y);
    refresh();

Y el problema desaparece!

No sólo eso, sino que tiene que tener esas tres líneas. Si comento hacia fuera mvprintw(1, 0, "(%i, %i)", l.x, l.y); o refresh();, o ambas cosas, el programa se bloquea como antes al llegar a un telepuerto.

¿Alguna idea sobre lo que podría ser la causa de este comportamiento?

ACTUALIZACIÓN: I intentó eliminar todas las advertencias (que en su mayoría eran advertencias sobre las comparaciones de números con signo / sin firmar), pero sólo 1 permanece hasta el momento:

warning: reference to local variable 'other' returned

Y el código:

Location& Location::operator = (Location other)
{
    if(this == &other)
        return other;
    x = other.x;
    y = other.y;
    return *this;
}

¿Qué hago para solucionar este aviso?

¿Fue útil?

Solución

Construir su operador de asignación de esta manera:
Siempre debe volver * esto (aunque fueran iguales). Pero ellos nunca ya que estaban creando una copia local (por lo que este no fue su error).

Location& Location::operator = (Location const& other)
{
    // Does it really matter if you assign to self?
    x = other.x;
    y = other.y;
    return *this;
}

La copia y de intercambio estándar parecía un poco exagerado para una clase tan simple.

PS. Usted debe fijar todas las advertencias (incluso si son tan simple como la falta de correspondencia sin firmar). Si no se soluciona les va a ser inmune a su potencia y no se dará cuenta de un problema real, ya que está rodeado de advertencia que usted está haciendo caso omiso. Así solucionarlos todos (IA gire siempre en la bandera que hace que el compilador tratar todas las advertencias como errores para que el código no se compila si hay algunas advertencias).

La forma correcta de aplicar el operador de asignación (o el camino bueno más comúnmente aceptada). Es el uso de la copia y de intercambio idioma:

// notice the parameter is passed by value (i.e. a copy).
// So the copy part is aromatically taken care of here.
// So now you just need tom implement the swap() part of the idiom.
Location& Location::operator = (Location other)
{
    this->swap(other);
    return *this;
}

void Location::swap(Location& other)
{
    std::swap(x, other.x);
    std::swap(y, other.y);
}

Otros consejos

Location& Location::operator = (Location other)
{
    if(this == &other)
        return other;
    x = other.x;
    y = other.y;
    return *this;
}

Esto devuelve una referencia. Cuando se devuelve la función, lo que pasa a other? (Se muere, y que usted se refiere a la nada.) Dado que esta es la clase que usted está tratando con todo el área del problema, esta es probablemente la causa. Re-organización que rodea a las hojas de la pila de código en una determinada condición en la que se hace referencia a la variable muertos "obras".

Cambiar a return *this, o simplemente eliminar la marca por completo. (Asignación de dos variables sin sucursal será probablemente siempre correr más rápido que la adición de una rama, en una CPU moderna.)

(Usted también debe tener en general, el parámetro por referencia, en lugar de por valor.)

Ha comprobado el código que está causando esta anomalía? El Heisenbug fenómenos citado aquí:

Un ejemplo común es un error que se produce en un programa que se compila con un compilador de optimización, pero no en el mismo programa cuando se compila sin optimización (por ejemplo, para generar una versión en modo de depuración)

Aquí están algunas pautas:

  • Condición de carrera? está usando hilos?
  • Indicador de desbordamiento en algún límite?
  • Ejecutar a través de su código valgrind para monitorear cualquier cambio inusual / errática en los buffers de memoria en algún lugar

Otra cita:

Una razón común para Heisenbug similar comportamiento es que la ejecución de un programa en modo de depuración menudo se limpia la memoria antes de que el programa se inicia, y las variables de fuerzas en ubicaciones de pila, en lugar de mantenerlos en los registros. Estas diferencias en la ejecución puede alterar el efecto de los errores que implica el acceso de miembros fuera de los límites o suposiciones incorrectas sobre el contenido inicial de la memoria. Otra razón es que los depuradores comúnmente proporcionan los relojes u otras interfaces de usuario que causan código adicional (por ejemplo, acceso de propiedad) para ser ejecutado, lo cual puede, a su vez, cambiar el estado del programa. Sin embargo, otra razón es un fandango en el núcleo, el efecto de un puntero corriendo fuera de límites. En C ++, muchos heisenbug son causadas por las variables sin inicializar.

Asegúrese de que los interruptores están apagados - sin optimización, información de depuración completa, clara construye cualquier existente, reiniciar el IDE y volver a compilar de nuevo ....

En primer lugar, su ubicación :: = operador debe ser como esto en su lugar:

Location& Location::operator = (const Location &other)
{
    if(this == &other)
        return *this;
    x = other.x;
    y = other.y;
    return *this;
}

Sin embargo, esto probablemente no explica el accidente. Malos punteros en la pila que aquí no se estrellan en la mayoría de las arquitecturas (suponiendo que x e y son int).

Ahora bien, este es un mandelbug, no un Heisenbug. Tienes a alguien en algún lugar de memoria corrupta cosa. Buena suerte.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top