Problem mit Array in Klasse



  • Hallo, ich habe eine Klasse brett, die einen char-Array enthält. Zunächst mal die Header-Datei:

    class brett {
    private:
    	char f[64];
    public:
    	brett();
    	~brett();
    	char lese(int x,int y);
    	bool schreibe(int x,int y,char value);
    };
    

    In der Deklaration habe ich dann im Konstruktor zunächst alle Werte auf ein Leerzeichen gesetzt, das geht noch problemlos. Auch kann ich dort auf die einzelnen Elemente des Arrays zugreifen. In den folgenden Funktionen lese() und schreibe() stürzt das Programm jedoch ohne Fehler ab, sobald ich versuche, ein Element des Arrays auszulesen oder zu ändern.
    Leider weiß ich nicht, woran das liegt, da in beiden Fällen das Element exisitert, ein Abruf von f[0] scheitert genauso.

    brett::brett() {
    
    	for (int i=0;i<8;i++)
    	{
    		for (int j=0;j<8;j++)
    		{
    			f[8*i+j]=' ';
    		}
    	}
    }
    
    brett::~brett() {
    
    }
    
    char brett::lese(int x,int y)
    {
    	if ((x>=0) && (x<8) && (y>=0) && (y<8))
    	{
    		int val=x+8*y;
    		char z=f[val]; // --> geht nicht, warum????
    		return z;
    	}
    	return '-';
    }
    
    bool brett::schreibe(int x,int y,char value)
    {
    	if ((x>=0) && (x<8) && (y>0) && (y<8))
    	{
    		f[x+8*y]=value; --> geht ebenfalls nicht!!!!
    		return true;
    	}
    	return false;
    }
    

    Über eine Antwort würde ich mich freuen!



  • Problem liegt nicht im gepostetem code. Funktioniert bei mir einwandfrei. Naja, bis auf die Tatsache dass es bei "schreibe" wohl y>=0 heißen soll.


  • Mod

    Lies dir bitte mal den dritten Link in meiner Signatur durch, welchen Code bei einem Laufzeitfehler für eventuelle Helfer am hilfreichsten ist.

    P.S.: Leerer Destruktor mal wieder. Wozu? Hast du das aus einem schlechten Buch? Internettutorials?



  • Hallo,
    der Debugger hat genau an der Zeile gestreikt, die ich angegeben habe, aber ich habe jetzt ein Minimalbeispiel, bei dem es nicht mehr funktioniert:

    brett* b=new brett();
    figur=new Piece();
    //Bis hier funktioniert ein Aufruf b->schreibe;
    figur->move(x2,y2,b);
    

    In der move-Funktion funktioniert dann der Aufruf von b->schreibe nicht mehr:

    void Piece::move(int xn,int yn, brett* b)
    {
    	b->schreibe(1,2,'a');
    }
    

    Daher vermute ich, dass mein Fehler bei der Übergabe des Brettes an die Funktion move liegt, leider weiß ich aber nicht, wie ich es besser machen soll.

    P.S. Der leere Destruktor ist ein Überbleibsel, weil ich den Array f zunächst auf dem Heap anlegen wollte, dann aber dachte, dass dort der Fehler stecken könnte.



  • Funktioniert bei mir einwandfrei.

    Wie wäre es denn, wenn du ein Minimalbeispiel postest?
    Das beinhaltet, das ich den code kopieren, bei mir einfügen, kompilieren kann und ich dann denselben Fehler bekomme.

    Lies dir doch bitte mal den dritten Link von SeppJ wirklich nochmal durch. Dann hättest du evtl schon beim ersten mal eine direkte Antwort bekommen - oder hättest gar nicht fragen müssen, weil du dann den Fehler selbst schon gefunden hättest.



  • Hi, hier jetzt mal ein ausführbares Minimalbeispiel, ich hab alle wichtigen Klassen gleich mal in eine Datei gepackt. Der Debugger stürzt bei einem Aufruf von b->lese(); ab, allerdings kann ich weit und breit keinen Fehler entdecken.

    ^/*
     * main.cpp
     *
     *  Created on: 02.06.2012
     *      Author: Thomas
     */
    
    #include <iostream>
    
    // Klasse für Spielfiguren
    class Piece
    {
    public:
    	Piece(int a,int b,int c);
    protected:
    	int x;
    	int y;
    	int besitzer;
    	bool active;
    };
    
    //Spielfeld 8x8
    class brett {
    private:
    	char f[64];
    public:
    	brett();
    	char lese(int x,int y);
    	bool schreibe(int x,int y,char value);
    };
    
    // regelt die Ausgabe, bei der der Fehler erfolgt
    class Interface
    {
    public:
    	void ausgabe(brett* b);
    };
    
    //Spielklasse, ruft alles auf
    class Game
    {
    private:
    	brett* b;
    	Interface aus;
    	int activeplayer;
    	bool end;
    	Piece *figur[32];
    
    public:
    	Game();
    	void zug();
    	int aendern(char a,int b,char c,int d);
    
    };
    
    //TRENN
    
    //Spielfeld leer am Anfang
    brett::brett() {
    	for (int i=0;i<8;i++)
    	{
    		for (int j=0;j<8;j++)
    		{
    			f[8*i+j]=' ';
    		}
    	}
    }
    
    //Spielfeld auslesen
    char brett::lese(int x,int y)
    {
    	if ((x>=0) && (x<8) && (y>=0) && (y<8))
    	{
    		int val=x+8*y;
    		char z=f[val];
    		return z;
    	}
    	return '-';
    }
    
    //Spielfeld schreiben
    bool brett::schreibe(int x,int y,char value)
    {
    	if ((x>=0) && (x<8) && (y>0) && (y<8))
    	{
    		f[x+8*y]=value;
    		return true;
    	}
    	return false;
    }
    
    //Figur erzeugen
    Piece::Piece(int a,int b,int c)
    {
    	x=a;
    	y=b;
    	besitzer=c;
    	active=true;
    }
    
    //Spielfeld ausgeben
    void Interface::ausgabe(brett* b)
    {
    	std::cout << "  a b c d e f g h" << std::endl << "  ---------------" << std::endl;
    	for (int i=0;i<8;i++)
    	{
    		std::cout << 8-i << "|";
    		for (int j=0;j<8;j++)
    		{
    			std::cout << b->lese(j,i) << " ";
    		}
    		std::cout << std::endl;
    	}
    
    }
    
    Game::Game()
    {
    	//neues Spielfeld
    	brett* b=new brett();
    
    	//Figur "t" auf Spielfeld an Position 0/0 schreiben
    	b->schreibe(0,0,'t');
    
    	//Figur erstellen
    	figur[0]=new Piece(0,0,1);
    
    	// hier würden weitere Figuren folgen
    }
    
    void Game::zug()
    {
    	aus.ausgabe(b);
    }
    
    int main()
    {
    	Game Spiel;
    	Spiel.zug();
    }
    


  • Habe mal Valgrind für dich bemüht, einige Fehler aufgezeigt:

    ethon@slaybook:~$ valgrind --tool=memcheck --track-origins=yes --leak-check=full ./bla
    ==12405== Memcheck, a memory error detector
    ==12405== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
    ==12405== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
    ==12405== Command: ./bla
    ==12405== 
      a b c d e f g h
      ---------------
    ==12405== Use of uninitialised value of size 8
    ==12405==    at 0x40094D: brett::lese(int, int) (in /home/ethon/bla)
    ==12405==    by 0x400A76: Interface::ausgabe(brett*) (in /home/ethon/bla)
    ==12405==    by 0x400B5F: Game::zug() (in /home/ethon/bla)
    ==12405==    by 0x400B8A: main (in /home/ethon/bla)
    ==12405==  Uninitialised value was created by a stack allocation
    ==12405==    at 0x400B77: main (in /home/ethon/bla)
    ==12405== 
    8|   �     
    7|        
    6|�   �     
    5|�   �     
    4|�   �     
    3|�   �     
    2|�   �     
    1|�   �     
    ==12405== 
    ==12405== HEAP SUMMARY:
    ==12405==     in use at exit: 80 bytes in 2 blocks
    ==12405==   total heap usage: 2 allocs, 0 frees, 80 bytes allocated
    ==12405== 
    ==12405== 16 bytes in 1 blocks are definitely lost in loss record 1 of 2
    ==12405==    at 0x4C2B1C7: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==12405==    by 0x400B10: Game::Game() (in /home/ethon/bla)
    ==12405==    by 0x400B7B: main (in /home/ethon/bla)
    ==12405== 
    ==12405== 64 bytes in 1 blocks are definitely lost in loss record 2 of 2
    ==12405==    at 0x4C2B1C7: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==12405==    by 0x400ADC: Game::Game() (in /home/ethon/bla)
    ==12405==    by 0x400B7B: main (in /home/ethon/bla)
    ==12405== 
    ==12405== LEAK SUMMARY:
    ==12405==    definitely lost: 80 bytes in 2 blocks
    ==12405==    indirectly lost: 0 bytes in 0 blocks
    ==12405==      possibly lost: 0 bytes in 0 blocks
    ==12405==    still reachable: 0 bytes in 0 blocks
    ==12405==         suppressed: 0 bytes in 0 blocks
    ==12405== 
    ==12405== For counts of detected and suppressed errors, rerun with: -v
    ==12405== ERROR SUMMARY: 66 errors from 3 contexts (suppressed: 2 from 2)
    


  • Dein Konstruktor von Game hat einen Fehler.

    brett* b=new brett(); //du erstellst hier ein lokales b, du willst aber dem b der Klasse einen sinnvollen Wert geben
    

    =>

    b=new brett(); //einfach brett* weglassen
    

    So ist der Fehler auch behoben.



  • Auch Ethons Beitrag lesen - du hast memory leaks, while du keinen Destruktor hast, um deine Zeigerchen wieder freizugeben.



  • Oder noch besser: Ab in die Initialisierungsliste des Konstruktors damit.
    Oder noch besser: std::unique_ptr benutzen.
    Oder noch besser: Das Brett zu einem direkten Member machen. Wieso überhaupt new?


Anmelden zum Antworten