Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (GNU/Linux, *NIX, *BSD und Co) » Buffer overrun bei Änderung von Klassenattributen

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
25.01.2006, 13:07 Uhr
~GCChris
Gast


Hallo,
nun habe ich fast alle C++Foren der Welt durchforstet und leider keine Lösung für ein (mir) unerklärliches Verhalten meines Programms gefunden. Ich fang mal mit einer Beschreibung des Programms an:

Mein Programm besteht aus zwei Klassen (Player und MD2Model). Player besitzt zwei Pointer auf Objekte der Klasse MD2Model, sowie einen Pointer auf ein Float-Vektor. (Player ist ein Singleton, also besitzt es noch eine Instanz von sich selbst)

C++:
#define PLAYER Player::get_player()
class Player
{
public:
    static Player* get_player();
    ~Player();
    void load_player_model1( char* f, char* t ) {mP1Model->load(f,t);}
    void load_player_model2( char* f, char* t ) {mP2Model->load(f,t);}
    void draw();
    void set_position( float x, float y, float z ) { mPosition[0] = x; mPosition[1] = y; mPosition[2] = z; }
private:
    static Player* mSingleton;
protected:
    Player();
    MD2Model *mP1Model;
    MD2Model *mP2Model;
    float *mPosition;
};



Die Implementierung sieht so aus:

C++:
Player::Player() {
    mP1Model = new MD2Model();
    mP2Model = new MD2Model();
    mPosition = new float[3];
    set_position( 0.0, 0.0, 0.0 );
}
Player *Player::mSingleton = 0;
Player*
Player::get_player() {
    if ( mSingleton == 0 ) {
        mSingleton = new Player;
    }
    return mSingleton;
}
void
Player::draw() {
    mP1Model->animate( 200, mPosition );
        mP2Model->animate( 200, mPosition );
}


Auf MD2Model gehe ich jetzt nicht weiter ein, da diese komplett getestet wurde. Sollte diese doch wichtig sein, lasst es mich wissen. Und der Fehler tritt selbst, wenn diese Klasse nur leere Methoden implementiert.

Main sieht so aus:

C++:
int main(...) {
    // hier kommt ein wenig GL Code...
    MD2Model *m1 = new MD2Model();
    MD2Model *m2 = new MD2Model();
    m1->load("mod1.md2","mod1.png");
    m2->load("mod2.md2","mod2.png");
    PLAYER->load("mod1.md2","mod1.png");
    PLAYER->load("mod2.md2","mod2.png");
    while(true) {
        m1->animate( 200, myPos );
        m2->animate( 200, myPos );
        PLAYER->draw();
    }
}



Bis hierher funktioniert noch alles wie gewünscht. (Ließt das hier überhaupt noch jemand? )
Fügt man nun Player ein weiteres Attribut beliebigen Typs zu (z.B. float mVelocity), dann kann auf mP1Model nicht mehr korrekt zugegriffen werden. Es kommt zwar beim Zugriff (egal welche Methode davon) zu keiner Speicherzugriffsverletzunge, aber sämtliche Daten des Objekts sind sind völlig verfälscht.

1) Es kommt zu keiner Speicherzugriffsverletzung - es wird halt nur Mist gezeichnet von MD2Model->animate.
3) gcc/ld spucken keine Warnung aus (gcc 3.4.2 und 3.4.4 getestet).
4) Verwendet man Tools wie Electric Fence, oder Duma, läuft das Programm problemlos. (Unabhängig davon, dass die Tools keine buffer over oder underrun anzeigen - also scheint es kein Problem mit der dynamischen Speicherbelegung zu geben) Dafür deutet es darauf hin, dass "Player" in den Speicherbereich von mP{1,2}Model "hineinragt". (Das würde erklären, warum es mit efence funktioniert, da dieser immer eine neue Seite belegt beim aufruf von malloc - stimmt das überhaupt???) (siehe 6.)
5) mPosition, mP{1,2}Model erst mit NULL zu initialisieren und dann "new MD2..." direkt vor ihrer Verwendung aufzurufen bringt auch nichts.
6) Aber..es ist immer das Modell betroffen, für das zuerst der Konstruktor (MD2Model()) aufgerufen wurde. Das andere Modell wird korrekt gezeichnet. (siehe 4.)

Vielleicht hat ja jemand von Euch eine Idee, oder sieht schon den Fehler.

Vielen Dank!
Christian
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
05.04.2006, 02:37 Uhr
0xdeadbeef
Gott
(Operator)


So wie ich das sehe, dürfte der Code nicht mal kompilieren, weil Player keine Methode load hat. Ansonsten verstehe ich nicht, warum du so viel auf den Heap packen willst, wos überhaupt nicht nötig ist, damit handelst du dir bloß unnötig Speicherlöcher ein. Warum nicht

C++:
class Player {
public:
  static Player &instance() {
    static Player me;
    return me;
  }

  void set_position(float x, float y, float z) {
    mPosition[0] = x;
    mPosition[1] = y;
    mPosition[2] = z;
  }

  void load_model1(char const *f, char const *t) { mP1Model.load(f, t); }
  void load_model2(char const *f, char const *t) { mP2Model.load(f, t); }

private:
  Player() { }
  Player(Player const &player) { }

  MD2Model mP1Model,
           mP2Model;
  float mPosition[3];
};


oder etwas in der Art?
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (GNU/Linux, *NIX, *BSD und Co) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: