Frage

Also ich bin eine Schlange Spiel mit teleports und die üblichen Mäuse machen. Ich hatte eine Schleife wie folgt ausgeführt werden:

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

Das Problem mit dem obigen Code war, dass displayInfo aufgerufen wird, bevor die Partitur aktualisiert wird, und so nach einer Maus zu essen, muss der Benutzer warten, bis die Schleife wieder läuft seine Partitur aktualisiert, um zu sehen. Also zog ich, dass eine Zeile Code auf den Boden der Funktion:

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

und teleports aufhören zu arbeiten! Das Programm stürzt ab, wenn die Schlange einen Teleport erreicht. Und displayInfo verwendet den folgenden Code:

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);

Wo printLine hat nur color_set, mvprintw und refresh(). Nichts mit Teleports zu tun. Schräge.

ging also ich auf die Schlange Funktion, wo die Schlange ihre nächste Position von einem Teleport wird:

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

Wo teleports[overlap(next)]->teleportFrom(dir) die Position kehrt die Schlange zu teleportiert werden soll. In einem Versuch, um zu sehen, warum es abstürzt (? Vielleicht Teleport eine Lage außerhalb des Bildschirms zurückkehrt), habe ich die folgenden drei Zeilen vor der Zeile oben:

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

Und das Problem verschwindet!

Nicht nur das, aber ich habe diese drei Linien haben. Wenn ich kommentieren Sie mvprintw(1, 0, "(%i, %i)", l.x, l.y); oder refresh(); oder beides, stürzt das Programm nach wie vor auf eine teleportieren zu erreichen.

Alle Ideen, was könnte dieses Verhalten verursachen?

UPDATE: Ich habe versucht, alle Warnungen zu entfernen (die über Vergleiche von signierten / unsigned Zahlen meist Warnungen waren), aber nur 1 bleibt so weit:

warning: reference to local variable 'other' returned

Und der Code:

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

Was kann ich tun, um diese Warnung zu beheben?

War es hilfreich?

Lösung

Erstellen Sie Ihre Zuweisungsoperator wie folgt aus:
Sie sollten immer zurückkehren * diese (auch wenn sie waren gleich). Aber sie würden nie da Sie eine lokale Kopie kreierten (so dies nicht Ihr Fehler war).

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

Die Standard-Kopie und Swap schien etwas übertrieben für eine solche einfache Klasse.

PS. Sie sollten alle Warnungen beheben (auch wenn sie so einfach wie die unsigned Mismatch) sind. Wenn Sie nicht beheben Sie immun gegen ihre Wirksamkeit und werden nicht ein echtes Problem erkennen, weil es mit der Warnung, umgeben ist, dass Sie ignorieren. So reparieren sie alle (aI drehen immer auf die Flagge, die der Compiler behandeln alle Warnungen als Fehler macht, so dass der Code nicht kompiliert, wenn es irgendwelche Warnungen).

Der richtige Weg Zuweisungsoperator (oder die am häufigsten akzeptierten guten Weg) zu implementieren. Ist es, die Kopie und Swap-Idiom zu verwenden:

// 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);
}

Andere Tipps

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

Das gibt eine Referenz. Wenn die Funktion zurück, was passiert mit other? (Es stirbt, und Sie beziehen sich auf nichts.) Da dies die Klasse ist es, um den Problembereich zu tun hat, ist dies wahrscheinlich die Ursache. Re-Arrangieren Blätter umgebender Code, den Stapel in einem bestimmten Zustand, in dem die Toten Variable „Werke“ Bezug genommen wird.

Ändern Sie ihn auf return *this, oder einfach nur den Scheck sogar komplett löschen. (Zuordnung von zwei Variablen ohne Zweig wird wahrscheinlich immer schneller laufen als ein Zweig hinzufügen, auf einer modernen CPU).

(Sie sollen auch die Parameter als Verweis im Allgemeinen nehmen, statt durch-Wert).

Haben Sie in Ihren Code, der diese Anomalie verursacht? Die Heisenbug Phänomene zitiert hier:

Ein gängiges Beispiel ist ein Fehler, der in einem Programm auftritt, die mit einem optimierenden Compiler kompiliert wurden, aber nicht in dem gleichen Programm, wenn ohne Optimierung kompiliert (beispielsweise zum Erzeugen einer Debug-Modus-Version)

Hier sind einige Richtlinien:

  • Race Condition? Sie sind Threads?
  • Zeigerüberlauf Grenze irgendwo?
  • Führen Sie Ihren Code durch valgrind irgendwo auf ungewöhnliche / erratischen Veränderungen in Speicherpuffer überwachen

Ein weiteres Zitat:

Ein häufiger Grund für Heisenbug-ähnliches Verhalten ist, dass ein Programm im Debug-Modus ausführen reinigt oft Speicher, bevor das Programm startet, und Kräfte Variablen auf dem Stapel Stellen, anstatt sie in den Registern zu halten. Diese Unterschiede in der Ausführung können die Wirkung von Bugs verändern Einbeziehung out-of-bounds Mitglied Zugang oder falsche Annahmen über die ursprünglichen Inhalte des Speichers. Ein weiterer Grund ist, dass Debugger häufig Uhren bieten oder eine andere Benutzerschnittstellen, die zusätzlichen Code verursacht (wie Eigenschaftenaccessoren) ausgeführt werden, was wiederum kann, um den Zustand des Programms ändern. Ein weiterer Grund ist ein Fandango auf Kern, der Effekt eines Zeigers der Grenzen zur Neige. In C ++ sind viele heisenbugs durch nicht initialisierte Variablen verursacht werden.

Stellen Sie sicher, dass die Schalter ausgeschaltet sind - keine Optimierung, vollständige Debug-Informationen, deaktivieren Sie alle vorhandenen baut, starten Sie den IDE und recompile wieder ....

Zu allererst Ihre Lage :: operator = sollte wie folgt statt sein:

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

Allerdings ist das wahrscheinlich den Absturz nicht erklären. Bad Zeiger auf Stapel hier nicht abstürzen auf den meisten Architekturen (vorausgesetzt, x und y int).

Nun, das ist ein mandelbug, kein Heisenbug. Sie haben jemand anderes irgendwo verderblichen Speicher. Viel Glück.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top