Board index
FAQ Search Members Groups Register Login
 
 
 

Post new topic Reply to topic  [ 113 posts ]  Go to page Previous  1 ... 3, 4, 5, 6, 7, 8  Next
Author Message
Post Posted: 28.04.2008 13:10  Post subject:
Offline
Heimwerkstatttuner
Heimwerkstatttuner
User avatar

Joined: 18.10.2004 15:02
Posts: 1113
Location: Schweiz
Dirk Plate wrote:
Mit der angegebenen Zeile erstellst du eine neue Liste im Speicher und speicherst in der Variable einen neuen Pointer. An der bestehenden Liste (wo der Pointer vorher hingezeigt hat) ändert sich durch die Zeile nichts.


Mh - irgendwie reden wir aneinander vorbei (ich formulier wahrscheinlich zu schlecht :/ ). Ich probiers nochmal:

Ich habe eine Funktion - die überprüft, ob bereits Daten eingelesen wurden - wenn nicht, wird das hier aufgerufen:

Code:
liste = new Koordinaten[10];
Einlesen der Daten aus einem File


Jetzt will der Benutzer nochmal Daten importieren (aus welchem Grund auch immer). Die Funktion wird wieder aufgerufen - überspringt aber den ersten Code Schnipsel, weil ja Daten schon importiert wurden. Es wird weitergesprungen zu diesem Code-Schnipsel:

Code:
grosseListe = new Koordinaten[10+5];

for(i=0;i<10;i++) grosseListe[i] = liste[i];
for(i=0;i<5;i++) grosseListe[10+i] = neueDaten[i];

delete [] liste;
liste = grosseListe;


Soweit so gut - wenn jetzt aber der Benutzer ein drittes mal importieren will, dann gibt's ein Problem - das Programm springt zur zweiten Codeliste und bleibt dann hängen (weil grosseListe ja schon existiert).

Quote:
Programmierst du in C oder C++?


C++. Aber für das hier sollte es glaub noch ausreichen sein, mit structs zu arbeiten (allzuhäufig sollte an sich sowieso nicht importiert werden).


Top
  Profile 
 
Post Posted: 30.04.2008 23:21  Post subject:
Offline
Schattenparker
Schattenparker
User avatar

Joined: 18.10.2004 18:02
Posts: 191
Location: Scherzingen
Eigentlich dürfte er beim dritten Durchlauf bei

grosseListe = new Koordinaten[10+5];

nicht hängen bleiben, da einfach der Pointer überschrieben wird.
grosseListe muss auch kein Klassenattribut oder ähnliches sein, sondern ist sinnvollerweise nur in dieser einen Funktion definiert:

Koordinaten *grosseListe;
grosseListe = new Koordinaten[10+5];

Ist vielleicht dann verständlicher.


Top
  Profile 
 
Post Posted: 01.05.2008 12:35  Post subject:
Offline
Heimwerkstatttuner
Heimwerkstatttuner
User avatar

Joined: 18.10.2004 15:02
Posts: 1113
Location: Schweiz
Ah - ich glaube jetzt wirds klarer. Ich habe

Koordinaten *grosseListe;

nicht in der Schleife sondern im Header definiert. Evt. liegts daran?


Top
  Profile 
 
Post Posted: 01.05.2008 15:46  Post subject:
Offline
Schattenparker
Schattenparker
User avatar

Joined: 18.10.2004 18:02
Posts: 191
Location: Scherzingen
Eigentlich sollte es egal sein.


Top
  Profile 
 
Post Posted: 03.05.2008 20:46  Post subject:
Offline
Heimwerkstatttuner
Heimwerkstatttuner
User avatar

Joined: 18.10.2004 15:02
Posts: 1113
Location: Schweiz
Mmmh - ich glaube es funktioniert. Allerdings kann ich es nicht richtig überprüfen :)

Folgendes Problem:

Code:
ImageDataCount2.open(FileName.c_str(), ios::in);
         while(!ImageDataCount2.eof())
         {
            getline(ImageDataCount2,temporary);
            amountOfMeasurementsBuff++;
         }
ImageDataCount2.close();


ImageDataCout2 ist ein fstream. Der wird bei jedem Importvorgang neu geöffnet und geschlossen. Das Problem:

Nach dem ersten öffnen, weigert sich C++ den fstream nochmal durchzugehen. D.h. beim zweiten öffnen befindet sich ImageDataCount2 scheinbar am Ende des Files und erhöht die Variable "amountOfMeasurementsBuff" nicht mehr.

Die obligatorische Frage die nun folgt: Was soll das? (Das Problem hatte ich aber auch schon früher - damals habe ich es mit verschiedenen Streams gelöst. Hier ist das aber nicht möglich (es befindet sich ja in einer Schleife).

Edit: Gelöst hab ich das Problem, dass ich jetzt vor den Schlaufen den fstream jedesmal neu definiere.

D.h.:

Code:
fstream ImageDataCount;


vor den Schleifen. Geht das auch anders?

Edit2: Und vielen Dank für den Tipp Dirk :)


Top
  Profile 
 
Post Posted: 04.05.2008 10:21  Post subject:
Offline
Schattenparker
Schattenparker
User avatar

Joined: 18.10.2004 18:02
Posts: 191
Location: Scherzingen
Nach dem ImageDataCount2.open kannst du noch folgendes einfügen:

ImageDataCount2.seekg(0); //File-Pointer zum Anfang setzen
ImageDataCount2.clear(); //Alle Flags zurücksetzen

Evt. reicht auch nur clear().
Diese alten Datei-Funktionen sind einfach Schrott. ;)


Top
  Profile 
 
Post Posted: 04.05.2008 10:48  Post subject:
Offline
Heimwerkstatttuner
Heimwerkstatttuner
User avatar

Joined: 18.10.2004 15:02
Posts: 1113
Location: Schweiz
Aaah - das clear ist mir entgangen. Mit seekg geht's nicht, da ich put/get nicht verwende.

Quote:
Diese alten Datei-Funktionen sind einfach Schrott. :wink:


Da geb ich dir recht.


Top
  Profile 
 
Post Posted: 27.05.2008 20:44  Post subject:
Offline
Heimwerkstatttuner
Heimwerkstatttuner
User avatar

Joined: 18.10.2004 15:02
Posts: 1113
Location: Schweiz
Ich hätte da noch 2 Verständnisfragen :)

1. Ich ging immer davon aus, dass wenn ich

Code:
delete []Pointer;


mache, dass der nicht mehr erreichbar ist. Scheinbar ist er es aber doch, wie man an diesem Beispiel sieht:

Code:
grosseListe = new Koordinaten[10+5];

for(i=0;i<10;i++) grosseListe[i] = liste[i];
for(i=0;i<5;i++) grosseListe[10+i] = neueDaten[i];

delete [] liste;
liste = grosseListe;


Gehe ich richtig in der Annahme, dass
Code:
delete []liste;
lediglich den Pointer wieder auf NULL setzt und mit
Code:
liste = grosseListe;
quasi der Pointer neu gesetzt wird?

2. Wenn ich einen Pointer auf einen Array habe der da heisst:

Code:
grosseListe = new Koordinaten[10+5];
und dann in einer nächsten Schleifen Iteration den gleichen Befehl wieder ausführe, diesmal aber mit einem grösseren Array

Code:
grosseListe = new Koordinaten[15 + 5];
, dass dann quasi grosseListe "formatiert" wird? D.h. wenn z.B. in
Code:
grosseListe[1].X
einen Wert drin hatte, wird der mit
Code:
grosseListe = new Koordinaten[15 + 5];
"gelöscht"? D.h. er ist nachher in der neuen Grossen Liste nicht mehr drin?


Top
  Profile 
 
Post Posted: 27.05.2008 21:00  Post subject:
Offline
Synetic Developer
Synetic Developer
User avatar

Joined: 18.10.2004 13:48
Posts: 757
Rechts neben dem Zuweisungsoperator steht der Ausdruck, der evaluiert wird (bei "grosseListe = new Koordinaten[10+5];" also die Speicheranforderung), dabei ist erstmal völlig egal, was mit dem Ergebnis passiert. Der Speichermanager weiß quasi nicht, in welchem Pointer die Adresse des neu angeforderten Blocks hinterlegt wird. Wenn du zwei Speicheranforderungen aufeinanderfolgend einem einzigen Pointer zuweist, dann ist der zuerst allokierte Block verloren (Speicherleck), kopiert wird auch nichts.

Wenn du per delete bzw. delete[] Speicher freigibst, wird auch tatsächlich nur der Speicher freigegeben, aber kein Pointer auf NULL gesetzt. Der Pointer zeigt danach unverändert auf einen dann ungültigen Speicherbereich. Weist du dem Pointer dann eine neue Adresse zu, zeigt er ab dann eben dahin, der alte Speicherbereich ist deshalb aber nicht wieder erreichbar.


Top
  Profile 
 
Post Posted: 27.05.2008 22:24  Post subject:
Offline
Heimwerkstatttuner
Heimwerkstatttuner
User avatar

Joined: 18.10.2004 15:02
Posts: 1113
Location: Schweiz
Daniel wrote:
Rechts neben dem Zuweisungsoperator steht der Ausdruck, der evaluiert wird (bei "grosseListe = new Koordinaten[10+5];" also die Speicheranforderung), dabei ist erstmal völlig egal, was mit dem Ergebnis passiert. Der Speichermanager weiß quasi nicht, in welchem Pointer die Adresse des neu angeforderten Blocks hinterlegt wird. Wenn du zwei Speicheranforderungen aufeinanderfolgend einem einzigen Pointer zuweist, dann ist der zuerst allokierte Block verloren (Speicherleck), kopiert wird auch nichts.



Okay - das scheint in etwa dem zu entsprechen, was ich mir gedacht habe (wobei ja Speicherleck nicht so toll klingt :) ).

Daniel wrote:

Wenn du per delete bzw. delete[] Speicher freigibst, wird auch tatsächlich nur der Speicher freigegeben, aber kein Pointer auf NULL gesetzt. Der Pointer zeigt danach unverändert auf einen dann ungültigen Speicherbereich. Weist du dem Pointer dann eine neue Adresse zu, zeigt er ab dann eben dahin, der alte Speicherbereich ist deshalb aber nicht wieder erreichbar.


Okay - auch das scheint das zu sein, was ich mir zusammengereimt habe. Super - danke! :) (Bis auf das NULL zeigen - das wird mit dem Destruktor gemacht - oder?).


Top
  Profile 
 
Post Posted: 27.05.2008 23:42  Post subject:
Offline
Synetic Developer
Synetic Developer
User avatar

Joined: 18.10.2004 13:48
Posts: 757
Hypothraxer wrote:
Okay - auch das scheint das zu sein, was ich mir zusammengereimt habe. Super - danke! :) (Bis auf das NULL zeigen - das wird mit dem Destruktor gemacht - oder?).


Nein, Destruktoren setzen keine Pointer auf das zu löschende Objekt auf NULL. Destruktoren sind eigentlich nur dazu da, den vom Objekt verwalteten zusätzlichen Speicher ebenfalls freizugeben oder sich z.B. aus Objektlisten auszutragen.


Top
  Profile 
 
Post Posted: 31.05.2008 12:17  Post subject:
Offline
Schattenparker
Schattenparker
User avatar

Joined: 18.10.2004 18:02
Posts: 191
Location: Scherzingen
Was man vielleicht noch dazu sagen sollte:
Wenn du den Speicher mit delete freigibst, kannst du zwar weiterhin mit dem Pointer darauf zugreifen... aber der Inhalt kann sich dann natürlich plötzlich verändern, da jemand anderes den freigegebenen Speicher verwendet.


Top
  Profile 
 
Post Posted: 31.05.2008 12:17  Post subject:
Offline
Heimwerkstatttuner
Heimwerkstatttuner
User avatar

Joined: 18.10.2004 15:02
Posts: 1113
Location: Schweiz
Daniel wrote:
Hypothraxer wrote:
Okay - auch das scheint das zu sein, was ich mir zusammengereimt habe. Super - danke! :) (Bis auf das NULL zeigen - das wird mit dem Destruktor gemacht - oder?).


Nein, Destruktoren setzen keine Pointer auf das zu löschende Objekt auf NULL. Destruktoren sind eigentlich nur dazu da, den vom Objekt verwalteten zusätzlichen Speicher ebenfalls freizugeben oder sich z.B. aus Objektlisten auszutragen.


Aaaaaah! D.h. es sollte an sich kein Speicherleck auftreten, wenn ich den Array so vergrössern will:

- Temporären Pointer erstellen und alte Werte reinschreiben.
- Alten Pointer löschen
- Neuen Pointer auf grösseren Array erstellen
- Werte aus temporärem Array in neuen Array reinschreiben
- Temporären Pointer löschen
- Neue Werte in neuen Array reinschreiben.

Mit anderen Worten: Meine Version wäre in dem Fall langsamer aber ohne Speicherleck - Dirk's schnelelr aber mit Speicherleck? (Wobei es in dem Fall wohl nicht so drauf ankommt, da die Datenmengen klein sind ;) ).


Top
  Profile 
 
Post Posted: 31.05.2008 14:33  Post subject:
Offline
Synetic Developer
Synetic Developer
User avatar

Joined: 18.10.2004 13:48
Posts: 757
Warum zweimal umkopieren? Normalerweise macht man das so:

- neues Array in passender Größe anfordern
- alte Werte rüberkopieren
- altes Array freigeben
- Arraypointer auf neues Array umbiegen
- neue Werte reinkopieren

So sieht die kleinstmögliche (keine Fehlerprüfung, keine besonderen Performanceoptimierungen) vollständige Implementation eines in der Größe veränderbaren Buffers aus:

Code:
template<class T>
class Buffer
{
private:
    T *pBuffer;
    size_t Size;
public:
    // default and copy constructor, destructor
    Buffer() : pBuffer(NULL), Size(0) {}
    Buffer(const Buffer &Src)
    {
        Size = Src.Size;
        pBuffer = new T[Size];
        for (size_t i = 0; i < Size; ++i)
            pBuffer[i] = Src.pBuffer[i];
    }
    ~Buffer()
    {
        delete[] pBuffer;
    }
    // assignment operator
    Buffer& operator=(const Buffer &Src)
    {
        if (this != &Src)
        {
            Size = Src.Size;
            delete[] pBuffer;
            pBuffer = new T[Size];
            for (size_t i = 0; i < Size; ++i)
                pBuffer[i] = Src.pBuffer[i];
        }
        return(*this);
    }
    // size operations
    size_t GetSize() const
    {
        return(Size);
    }
    void SetSize(size_t NewSize)
    {
        T *pNewBuffer = (NewSize > 0) ? new T[NewSize] : NULL;
        size_t CopySize = (Size < NewSize) ? Size : NewSize;
        for (size_t i = 0; i < CopySize; ++i)
            pNewBuffer[i] = pBuffer[i];
        delete[] pBuffer;
        pBuffer = pNewBuffer;
        Size = NewSize;
    }
    // array access operators
    const T& operator[](size_t i) const
    {
        return(pBuffer[i]);
    }
    T& operator[](size_t i)
    {
        return(pBuffer[i]);
    }
};


Top
  Profile 
 
Post Posted: 03.06.2008 16:32  Post subject:
Offline
Heimwerkstatttuner
Heimwerkstatttuner
User avatar

Joined: 18.10.2004 15:02
Posts: 1113
Location: Schweiz
Daniel wrote:
Warum zweimal umkopieren?



Weil ich noch nicht so erfahren bin :) Ich schau mir Deinen Code bei Gelegenheit an - ich habe zwar noch nie mit Templates gearbeitet, aber ich schätze es sollte schon gehen. Vielen Dank auf jeden Fall.


Top
  Profile 
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 113 posts ]  Go to page Previous  1 ... 3, 4, 5, 6, 7, 8  Next


Who is online

Users browsing this forum: No registered users and 0 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  



 
   
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group