2013-02-28 4 views
7

Ich hatte ein Problem, bei dem mein Code beim Versuch, die size() -Funktion einer Liste zu verwenden, segfaulted. Auf den Rat von stackoverflow :-) Ich konstruierte einen minimalen Fall, in dem der segfault auftritt (auf dem Aufruf inventory.size() unten). Es ist:Array-Setup im Konstruktor bedeutet Fehler zu einem späteren Zeitpunkt

#include <list> 

class Thing {}; 

class Player { 
private: 
    int xpCalcArray[99]; 
    std::list<Thing*> inventory; 

public: 
    Player(); 

    int addToInv(Thing& t); // return 1 on success, 0 on failure 
}; 

Player::Player() { 
    // set up XP calculation array 
    for (int i=1; i<100; i++) { 
    if (i<=10) { 
     xpCalcArray[i] = i*100; 
    } 
    if (i>10 && i<=50) { 
     xpCalcArray[i] = i*1000; 
    } 
    if (i>50 && i<=99) { 
     xpCalcArray[i] = i*5000; 
    } 
    } 
} 

int Player::addToInv(Thing& t) { 
    if (inventory.size() == 52) { 
    return 0; 
    } else { 
     inventory.push_back(&t); 
    } 
    return 1; 
} 

int main(int argc, char *argv[]) { 
    Thing t; 
    Player pc; 
    pc.addToInv(t); 
    return 1; 
} 

Ich stelle fest, dass, wenn ich die Einrichtung des Arrays in dem Spieler cosntructor entfernen, es funktioniert gut, so das sieht das Problem sein. Was mache ich falsch?

+2

+1: Testfall! Ausgezeichnet! –

Antwort

2

Sie greifen außerhalb der Grenzen Ihres Arrays zu. Dies führt zu undefiniertem Verhalten und somit gibt es keine logische Erklärung für alles, was danach passiert. Die Größe Ihres Arrays ist 99 und der letzte Index ist 98. Ihre for Schleife geht jedoch bis 99.

machen Entweder Ihre Array-Größe 100:

int xpCalcArray[100]; 

Oder Ihren for Zustand zu i < 99 ändern.

4

Sie greifen auf Ihr Array außerhalb der Grenzen zu, was zu undefiniertem Verhalten führt. Der gültige Indexbereich für dieses Array

int xpCalcArray[99]; 

0 bis 98. Sie sind Index 99 Zugriff hier:

if (i>50 && i<=99) { 
    xpCalcArray[i] = i*5000; 
} 

Ihre äußere Schleife

for (int i=0; i<99; i++) { ... } 

Hinweis sein sollte ich von 0 beginnen obwohl es eine Annahme ist, dass Sie tatsächlich auf das erste Element zugreifen möchten.

Dann können Sie Ihre endgültige Zustand

if (i>50) { 
    xpCalcArray[i] = i*5000; 
} 

zu

vereinfacht werden, wenn Sie eine Größe 100 Array verwendet werden soll, dann müssen Sie

int xpCalcArray[100]; 

dann Schleife zwischen int i=0; i<100;.

+2

Und natürlich, würde man eine * single constant * anstatt hart codieren 50, 98, 99 und 100 überall ... –

+0

Danke euch allen. Do. – KHekkus

2

Sie überschreiben Ihr Array von 99 int s, indem Sie versuchen, die 2. → 100. Elemente zu ändern (statt 1. → 99.).

In Ihrem Fall geschieht dies etwas Speicher innerhalb der std::list<Thing*> überschrieben werden (die direkt nach dem Array im Speicher vorhanden ist — nicht immer, aber offenbar für Sie heute) und damit, wenn Sie versuchen, die Liste zu verwenden, werden alle Die Hölle bricht los, wenn ihre internen Mitgliedsdaten nicht mehr so ​​sind, wie sie gedacht haben.

1

Sie xpCalcArray ist definiert von 0 bis 98 (99 Elemente groß).

Ihre Schleife geht von 0 bis 99 und nimmt dabei 100 Schritte.

Der letzte Schleifenzyklus, schreibt xpCalcArray an der Stelle 99, die nicht existiert. Dies führt (indirekt) zu Ihrem Segmentierungsfehler, wie von the answer of Lightness Races in Orbit gezeigt.

So erhöhen Sie die Größe von xpCalcArray von 1:

int xpCalcArray[100]; 
+0

Es _indirectly_ führt zum Segmentierungsfehler. Die einzige direkte Konsequenz hier ist das Aufrufen von UB. –

+0

Ja, Sie haben Recht, Ihre zusätzliche Erklärung der Ursache ist ausgezeichnet! – Veger

+0

Ohne die beabsichtigte Logik des Codes zu kennen, ist die Vergrößerung des Arrays nicht unbedingt die richtige Lösung. Es könnte sein, aber wir können nicht sicher sein. – juanchopanza

Verwandte Themen