Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Probleme mit Zeigern

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 < [ 2 ]
000
29.05.2010, 10:16 Uhr
~jojo
Gast


Hallo Forengemeinde,

zurzeit habe ich an der Uni Programmieren für Ingenieure und habe jetzt mal eine Frage zu einer Übung:

Ich soll eine Liste anlegen in der eine (zur Compilezeit) unbekannte Menge an Objekten abgelegt werden soll:

C++:
class SceneObjectList
{
private:
    /**
    *  The internal data pointer
    **/

    SceneObject** data;

    /**
    *  Size of the data array, Number of elements
    *  currently stored in this list
    **/

    int arraySize, numberElements;
public:
    /**
    *  Creates a new list of zero objects
    **/

    SceneObjectList();

    /**
    *  Adds a new object to the list. If the internal array
    *  is full you have to create a new array with 2 * arraySize
    *  slots and copy the old data into the new array. Don't forget to
    *  free the memory after the copy step!
    **/

    void add(SceneObject* object);
    
    /**
    *  Removes the first occurance of the given object from the list.
    *  In order to remove the Element from the list you have to move
    *  all elements that are behind the index of the found element one
    *  index to the front. If the given object was removed successfully
    *  the old index of the element is returned, -1 otherwise.
    **/

    int remove(SceneObject* object);

    /**
    *  Resets the number elements to zero.
    **/

    void clear();

    /**
    *  Returns the number of elements stored in the list
    **/

    int count();

    /**
    *  Returns the index'th element in the list. If the given index
    *  is not valid (< 0 or >= count) you have to return a NULL pointer.
    **/

    SceneObject* getObject(int index);

    /**
    *  Destroys the list and frees allocated memory
    **/

    ~SceneObjectList();
};



Soweit ist auch alles klar (das ist so vorgegeben).

Jetzt habe ich bei meiner add Funktion ein Problem:


C++:
void SceneObjectList::add(SceneObject* object)
{
    if (numberElements < arraySize)
        {
        data[numberElements] = object;
        numberElements++;
        }
    else
        {
        SceneObject** data2;
        data2 = new SceneObject*[arraySize*2];
        for (int i = 0; i < (numberElements); i++)
            data2[i] = data[i];
        //delete data;
        data = data2;
        data[numberElements] = object;
        numberElements++;
        }
}



Die Größe nach dem Konstruktor Aufruf ist 2. Ein einfaches Besetzen dieser beiden Plätze funktioniert. Jedoch wenn ich nun mehrere Elemente noch hineinschreiben will stürzt das Programm ab und zwar beim Aufruf des new SceneObject*[arraySize*2] ab (habe das ganze versucht zu debuggen...).

Habe ich etwas übersehen?

Mfg und vielen Dank im Vorraus

jojo
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
29.05.2010, 10:47 Uhr
~R0C7KC
Gast


erstmal generell. Welche sprache sollst du proggen , c++ wäre es komplett falsch.
Dann womit compilierst du.

MfG.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
29.05.2010, 11:02 Uhr
~jojo
Gast


Sprache wäre C++ mit dem Microsoft Visual Studio 2008.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
29.05.2010, 11:12 Uhr
~R0C7KC
Gast


Okay. Du musst auf jeden fall includen und die main hast du auch nicht drin. Das ist ein großer fehler. Muss selbst erstmal gucken , ich gucke mal ob ich nachher noch einen sourcecode finde
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
29.05.2010, 11:34 Uhr
0xdeadbeef
Gott
(Operator)


Du löschst das alte data-Array nie; geht dir vielleicht einfach der Speicher aus?

Jedenfalls solltest du

C++:
//delete data;


durch

C++:
delete[] data;


ersetzen.

Außerdem...gibt es einen Grund, warum du nicht einfach einen STL-Container benutzt, beispielsweise std::deque?
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
29.05.2010, 11:38 Uhr
ao

(Operator)


Das auskommentierte "// delete data;" muss natürlich wieder rein, sonst verlierst du den alten Speicher. Und es heißt richtig "delete [] data;", weil das ein Array ist, kein einzelnes Objekt.

Außerdem fehlt am Ende "arraySize *= 2;"

Warum es abstürzt, weiß ich aber auch nicht, einen solchen Fehler kann ich nicht erkennen. Hast du die Membervariablen (arraySize und numberElements) richtig initialisiert?

Sonst poste mal ein kompilierbares Main-File, aber möglichst kein Riesenprogramm, sondern eins, was nur den Fehler demonstriert.

Dieser Post wurde am 29.05.2010 um 11:39 Uhr von ao editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
29.05.2010, 12:34 Uhr
~jojo
Gast


Erstmal vielen Dank für die schnelle Antworten.

Leider kann ich die Grundstruktur des Programms nicht ändern, es wurde uns so vorgegeben und wir sollen es nur vervollstädnigen (ansonste bekomme ich unter Umständen Probleme mit den automatischen Tests).

Hier mal ein Beispiel mit dem geschilderten Problem (Includes etc. fehlen nur hier im Beispiel):


C++:
SceneObjectList a;
a = SceneObjectList::SceneObjectList();
for (int i = 0; i < 2; i++)
    a.add(SceneObjectFactory::createBlueSphere(Point(0,10,0),5)); //hier wird einfach ein element erzeugt und an die liste gehangen
cout << "einfacher Add test bestanden" << endl;
for (int i = 0; i < 10; i++)
    a.add(SceneObjectFactory::createBlueSphere(Point(0,10,0),5));
cout << "schwerer add test bestanden" << endl;



und hier mal noch der komplette Code der Klasse:


C++:
SceneObjectList::SceneObjectList()
: arraySize(2), numberElements(0), data(new SceneObject*[2])
{ }

void SceneObjectList::add(SceneObject* object)
{
    if (numberElements < arraySize)
        {
        data[numberElements] = object;
        numberElements++;
        }
    else
        {
        SceneObject** data2;
        data2 = new SceneObject*[arraySize*2];
        for (int i = 0; i < (numberElements); i++)
            data2[i] = data[i];
        delete[] data;
        data = data2;
        arraySize = arraySize*2;
        data[numberElements] = object;
        numberElements++;
        }
}

int SceneObjectList::remove(SceneObject* object)
{
    //mehr als ein element im Speicher?
    //Löschhen, alle nachfolgenden eins nach vorne kopieren
    return -1;
}

SceneObject* SceneObjectList::getObject(int index)
{
    if ((index > numberElements) || (index < 0))
        return NULL;
    return data[index];
}

int SceneObjectList::count()
{
    return numberElements;
}

void SceneObjectList::clear()
{
    numberElements = 0;
}

SceneObjectList::~SceneObjectList()
{    
    for (int i = 0; i < (numberElements);i++)
            delete data[i];
    delete data;
    data = NULL;
}



Das delete Data nur den Zeiger löscht scheint unter der 2008 Visual studio version nicht mehr zu stimmen (sagte unser bremser), das wäre äquivalent zu delete[] Data (es macht auch keinen Unterschied.

mfg

Jojo

PS: das soll mal ein Raytracer werden, daher SceneObjectFactory etc...

Bearbeitung von 0xdeadbeef:

cpp-Tag geradegezogen


Dieser Post wurde am 29.05.2010 um 12:47 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
29.05.2010, 13:14 Uhr
0xdeadbeef
Gott
(Operator)



C++:
a = SceneObjectList::SceneObjectList();


Sowas hab ich ja noch nie gesehen. Ist das schlicht ein temporäres Objekt mit merkwürdigem Lookup?

Ansonsten muss das natürlich auch im Destruktor delete[] heißen.

Allerdings würde ich mir den ganzen Aufriss sparen und einfach std::deque benutzen. Beispiel:

C++:
#include <deque>

class SceneObjectList
{
private:
  std::deque<SceneObject*> data;

public:
  SceneObjectList();

  void add(SceneObject* object);
  int remove(SceneObject* object);
  void clear();
  int count();
  SceneObject* getObject(int index);

  ~SceneObjectList();
};

SceneObjectList::SceneObjectList()
{ }

void SceneObjectList::add(SceneObject* object)
{
  data.push_back(object);
}

int SceneObjectList::remove(SceneObject* object)
{
  return -1;
}

SceneObject* SceneObjectList::getObject(int index)
{
  if(index > data.size()) {
    return NULL;
  }

  return data[index];
}

int SceneObjectList::count()
{
  return data.size();
}

void SceneObjectList::clear()
{
  while(!data.empty()) {
    delete data.front();
    data.pop_front();
  }
}

SceneObjectList::~SceneObjectList()
{    
  clear();
}


Natürlich ist das ganze noch einfacher, wenn du Boost benutzt, speziell Boost Pointer Container.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
29.05.2010, 15:00 Uhr
Hans
Library Walker
(Operator)



Zitat von 0xdeadbeef:

Allerdings würde ich mir den ganzen Aufriss sparen und einfach std::deque benutzen.
...
Natürlich ist das ganze noch einfacher, wenn du Boost benutzt, speziell Boost Pointer Container.


Hey Beefy, wir wissen ja, das Du ein "Fan" davon bist, aber anscheinend hast Du jetzt auch mal was übersehen:

Zitat von ~jojo:
Leider kann ich die Grundstruktur des Programms nicht ändern, es wurde uns so vorgegeben und wir sollen es nur vervollstädnigen (ansonste bekomme ich unter Umständen Probleme mit den automatischen Tests).

Allerdings trau ich Dir auch zu, das Du das mit Absicht übersehen hast...

Hans
--
Man muss nicht alles wissen, aber man sollte wissen, wo es steht. Zum Beispiel hier: Nachdenkseiten oder Infoportal Globalisierung.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
29.05.2010, 15:46 Uhr
ao

(Operator)



Zitat von 0xdeadbeef:
Allerdings würde ich mir den ganzen Aufriss sparen ...


Klar würdest du das. Aber die Übungsaufgabe ist nun mal, die Objekteverwaltung zu schreiben, und zwar unter Verwendung der vorgegebenen Klasse.

Ich hab das Ganze mal rudimentär lauffähig gemacht, und bei mir (VS 2010 Release-Candidate) kracht der delete[]-Aufruf mit einer Heap-Corruption, und zwar gleich beim ersten Mal, wenn das Programm da vorbeikommt und das Array verlängern will.

Lasse ich delete[] weg, dann knallt es im Destruktor beim Programmende.

Ich steh momentan etwas aufm Schlauch, wie immer, wenn ich Doppelpointer sehe, und ich muss gleich auch weg, aber eins scheint festzustehen: Die Speicherorganisation wird zerstört. Ich empfehle, mal zu prüfen, ob die KONstruktion des Listenobjekts OK ist.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 < [ 2 ]     [ C / C++ (ANSI-Standard) ]  


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: