3 Stimmen

Segfault beim Aufruf einer virtuellen Methode für ein initialisiertes Objekt

Ich erhalte einen seg-Fehler, den ich nicht verstehe. Ich bin mit der Wt-Bibliothek und tun einige ausgefallene Dinge mit Signalen (die ich nur erwähnen, weil es mir ermöglicht hat, zu versuchen, dies zu debuggen).

Ich erhalte einen Zeiger auf eines meiner Widgets aus einem Vektor und versuche, eine Methode auf dem Objekt aufzurufen, auf das er zeigt. Gdb zeigt, dass der Zeiger auflöst, und wenn ich das Objekt untersuche, auf das er zeigt, ist es genau das, das ich ändern muss. In diesem Fall sendet das Widget an sich selbst, so dass es sowohl als Sender als auch als Hörer registriert ist; daher konnte ich auch überprüfen, ob der Zeiger "Sender" und der Zeiger "Hörer" auf dasselbe Objekt zugreifen. Das tun sie!

Doch obwohl ich sehen kann, dass das Objekt existiert, initialisiert ist und tatsächlich das richtige Objekt ist, erhalte ich einen sofortigen Seg-Fehler, wenn ich versuche, eine Methode für das Objekt aufzurufen. Ich habe einige verschiedene Methoden ausprobiert (einschließlich einiger boolescher Rückgaben, die das Objekt nicht verändern). Ich habe versucht, sie über den Broadcaster-Zeiger und den Listener-Zeiger aufzurufen, nur um eine Fehlersuche zu ermöglichen.

Der Debugger betritt das Objekt nicht einmal; der Segfault tritt sofort beim Versuch auf, eine Methode aufzurufen.

Code!

/* listeners is a vector of pointers to widgets to whom the broadcasting widget
 * is trying to signal.
 */
unsigned int num_listeners = listeners.size();
for (int w = 0; w < num_listeners; w++)
{
    // Moldable is an abstraction of another widget type
    Moldable* widget = listeners.at(w);

    /* Because in this case, the broadcaster and the listener are one in the same, 
     * these two point to the same location in memory; this part works. I know, therefore,
     * that the object has been instantiated, exists, and is happy, or we wouldn't
     * have gotten to this point to begin with. I can also examine the fields with gdb
     * and can verify that all of this is correct.
     */
    Moldable* broadcaster_debug = broadcast->getBroadcaster();

    /* setStyle is a method I created, and have tested in other instances and it
     * works just fine; I've also used native Wt methods for testing this problem and
     * they are also met with segfaults. 
     */
    widget->setStyle(new_style); // segfault goes here!
}

Ich habe seit der Recherche gelesen, dass das Speichern von Zeigern in Vektoren nicht die beste Idee ist und ich sollte in boost::shared_ptr schauen. Das mag so sein, und ich werde mich damit befassen, aber es erklärt nicht, warum der Aufruf einer Methode auf ein Objekt, von dem man weiß, dass es existiert, einen Segfault verursacht. Ich würde gerne verstehen, warum das passiert.

Danke für jede Hilfe.

Bearbeiten: Ich habe einen Gist mit den Vektor-Operationen detailliert erstellt, weil es mehr Code war, als bequem in den Beitrag passen würde. https://gist.github.com/3111137

Ich habe den Code, in dem die Widgets erstellt werden, nicht gezeigt, weil es sich um einen rekursiven Algorithmus handelt und ich dafür den gesamten Entscheidungsbaum der Klasse für die Erstellung von Widgets zeigen müsste. Es genügt zu sagen, dass die Widgets erstellt werden; ich kann sie auf der Seite sehen, wenn ich die Anwendung in einem Browser betrachte. Alles funktioniert gut, bis ich anfange, mit meinen ausgefallenen Signalen zu spielen.

Moar Edit: Wenn ich mir die Disassemblierung im Befehlsschrittmodus ansehe, kann ich sehen, dass kurz vor dem Auftreten des Segfehlers die folgende Operation stattfindet, deren erstes Argument als "void" aufgeführt ist. Zugegeben, zu meinem Leidwesen weiß ich nichts über Assembly, aber das scheint wichtig zu sein. Kann mir jemand erklären, was diese Anweisung bedeutet und ob sie die Ursache für meine Probleme sein könnte?

 add $0x378,%rax //$0x378 is listed as 'void'

Eine weitere Bearbeitung: Auf Anregung von jemandem habe ich eine nicht-virtuelle Methode erstellt, die ich kurz vor dem Seg-Fehler erfolgreich aufrufen kann, was bedeutet, dass das Objekt tatsächlich vorhanden ist. Wenn ich die gleiche Methode nehme und sie virtuell mache, tritt der Seg-Fehler auf. Warum erzeugen also nur virtuelle Methoden einen Seg-Fehler?

Ich habe jetzt entdeckt, dass wenn ich in der aufrufenden Klasse sicherstelle, dass Moldable::debug_test (und Moldable::setStyle) angegeben wird, der Seg-Fehler nicht auftritt. Allerdings scheint dies einen ähnlichen Effekt zu haben wie const bubbling - jede virtuelle Methode scheint diesen Spezifizierer zu wollen. Ich habe dieses Verhalten noch nie beobachtet. Während ich bereit bin, meinen Code zu korrigieren, wenn das WIRKLICH so sein soll, bin ich nicht sicher, ob das Root-Problem etwas anderes ist.

Es geht voran!

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X