Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » nach strcpy wird destructor ausgeführt

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
30.12.2007, 16:13 Uhr
RedEagle



Volgendes Szenario:

cfg.hpp

C++:
union CFGVALUE
{
bool  b;
char  c;
char *s;
short i;
long  l;
float f;
};

class CFGITEM
{
public:

  CFGITEM();
  CFGITEM(string name, string type, string value);
  ~CFGITEM();

//...

  operator char*();

//...

  CFGITEM *next; //Nachstes Item
  string name;   //Name des Items
  string type;   //Typ des Item-wertes
  string value;  //Wert des Items (ASCII-Codiert)

//..

  CFGVALUE cfgvalue;  //Enthält den umgewandelten wert (ist union)
};

////////////////////////////////////////////////////////////////////

class CFGGROUP
{

//...

  CFGITEM operator[](string itm);

//...

};

////////////////////////////////////////////////////////////////////

class CFGFILE
{

//...

  CFGGROUP operator[](string grp);

//...

};



Methoden der CFGITEM-Klasse

C++:
//...

CFGITEM::~CFGITEM()
{
if(this->type == "s"/* && this->converted*/ && this->cfgvalue.s != NULL)
{
  /**/cout << "*#*\n";
  delete[] this->cfgvalue.s; //Speicher des strings freigeben
}
return;
}

//...

CFGITEM::operator char*()
{
//Alles OK?
if(this->type != "s") return NULL;

//zurückgeben
return this->cfgvalue.s;
}

//...




Testprogramm

C++:
#include <cstdlib>
#include "cfg.hpp"

int main(int argc, char *argv[])
{
CFGFILE test("./test.txt");

char c[500];
strcpy(c,(char*)test["gruppe1"]["itemS2"]); //führ destructor aus

char *ptr;
ptr = test["gruppe1"]["itemS3"]; //führ destructor aus

return 0;
}


c enthält nun den string, den ich haben möchte. Die Addresse wird also von test richtig an strcpy übergeben. Das Problem ist nur, dass anschließend das item gelöscht wird (der destructor schreibt "*#*" in die Konsole, und das wars. Wenn ich dann erneut auf das item zugreifen möchte, bekomme ich die fehlermeldung, dass ich ein item "deleten" möchte, welches bereits gelöscht ist:
Selbes problem, wenn ich einfach nur die Adresse kopieren möchte.

error:
*** glibc detected *** ./test: double free or corruption (fasttop): 0x080532d0 ***


Was ist falsch?? Wo muss ich den Fehler suchen??
--
MFG RedEagle

Dieser Post wurde am 30.12.2007 um 16:25 Uhr von RedEagle editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
30.12.2007, 17:13 Uhr
Kest
saint


Hi!

Weil >test["gruppe1"]["itemS2"]< ein temporäres Objekt des Typs >CFGITEM< erzeugt. Und da es temporär ist, wird es, nachdem strcpy seine Arbeit erledigt hat, zerstört; folglich wird der Destruktor aufgerufen.
Bei >ptr = test["gruppe1"]["itemS3"];< zeigt >ptr< auf ein Objekt, das nach der Zuweisung wieder zerstört wird.
--
Wenn man einen Hufschlag hört, sollte man >Pferd< denken und nicht >Zebra<.

Dieser Post wurde am 30.12.2007 um 17:20 Uhr von Kest editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
30.12.2007, 20:06 Uhr
RedEagle



Wiso wird ein temporäres objekt erzeugt?
Aber wenn ein temporäres objekt zerstört wird, ist das ja kein Problem, es müsste doch bei beim nächsten mal erneut erzeugt werden?

mein problem ist aber, dass ich nur einmal auf dieses objekt (per char*() - operator) drauf zugreifen kann.

Ich kann in diesem objekt auch andere Werte (z.B. int) speichern. Dort tritt dieses Problem nicht auf (dort wird auch kein destructor aufgerufen):

C++:
long x;
x = test["gruppe2"]["itemL"];
cout << endl << "gruppe2; itemL = " << x << endl;
x = test["gruppe2"]["itemL"];
cout << endl << "gruppe2; itemL = " << x << endl;


C++:
CFGITEM::operator long()
{
//Alles OK?
if(this->type != "l") return 0;

//zurückgeben
return this->cfgvalue.l;
}

--
MFG RedEagle
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
30.12.2007, 21:11 Uhr
Kest
saint


Allgemein zu den temporären Objekten:
z.B.:
C++:
int x = 12;
int y = 34+x*x;


Das Zwischenergebnis >x*x< muss irgendwo gespeichert werden; es wird auch als ein temporäres Objekt bezeichnet. Nach dem das Ergebis an >y< zugewiesen wird, wird dieses Zwischenergebnis gelöscht. Logisch, weil es nicht mehr gebraucht wird.


Zitat von RedEagle:
Ich kann in diesem objekt auch andere Werte (z.B. int) speichern. Dort tritt dieses Problem nicht auf (dort wird auch kein destructor aufgerufen):

Ist ja auch selbstverständlich, weil fundamentale Typen gewöhnlich als >copy by value< geliefert werden, außer man erzwingt >copy by reference<.
Ein Zeiger dagegen zeigt auf etwas; in deinem Fall auf ein Objekt, das zerstört wurde.


Zitat von RedEagle:
(dort wird auch kein destructor aufgerufen)

Aufgerufen bestimmt. Dass aber nichts ausgegeben wird, könnte an >type == "s" && cfgvalue.s != NULL< liegen.

Ein ein wenig anschaulicherer Beispiel wäre:

C++:
#include <iostream>
#include <string>


class A
{
    typedef std::char_traits<char> CT;

    public:
            A(const char* a){
                cur = new char[CT::length(a)+1];
                CT::move(cur, a, CT::length(a)+1);
            }
            ~A(){ delete[] cur; }

            const char* c_str() const{ return cur; }

    private:
            char* cur;
};


int main()
{
    A a("hallo");
    const char* za = a.c_str();
    std::cout << za << std::endl;

    const char* zb = A("ich bin's").c_str();
    std::cout << zb << std::endl;
}


>zb< zeigt zwar auf etwas; aber auf etwas, was schon nicht mehr existiert. Es könnte aber auch sein, dass die doch ausgegeben wird, aber wenn schon, dann nur zufällig.
--
Wenn man einen Hufschlag hört, sollte man >Pferd< denken und nicht >Zebra<.

Dieser Post wurde am 30.12.2007 um 21:32 Uhr von Kest editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
30.12.2007, 22:03 Uhr
RedEagle



OK, jetzt weiß ich was du mit den temporären objekten meinst.

Aber in meinem Fall gebe ich, egal ob int oder char* eine DWORD (also einen Wert) zurück.
Dieser Wert kann als Zeiger interpretiert werden oder nicht. Was man damit macht, hat ja im prinzip nichts mehr mit dem CFGITEM-objekt zu tun.

zwischen

C++:
long x;
x = test["gruppe2"]["itemL"];

und

C++:
char *ptr;
ptr = test["gruppe1"]["itemS3"];

sollte doch eigentlich kein unterschied sein.

hier wird in beiden Fällen ein Wert kopiert, oder macht der kompiler da irgendetwas anderes raus?.
--
MFG RedEagle
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
30.12.2007, 23:23 Uhr
Kest
saint


Ein Zeiger wird im Gegensatz zu einfachen Typen deferenziert.
--
Wenn man einen Hufschlag hört, sollte man >Pferd< denken und nicht >Zebra<.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
30.12.2007, 23:56 Uhr
xXx
Devil


Hab jetzt nicht alles gelesen, aber du solltest dir dringendst mal (konst.) Referenzen angucken. Du kopierst ja überall!
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
31.12.2007, 00:01 Uhr
RedEagle



??

Ich derefenziere ja nichts, ich möchte nicht den Wert zurückgeben, auf den der Zeiger zeigt, sondern den Zeiger selber - also nur einen normalen Wert (bzw eine Adresse).

Ich gebe doch nur den Wert einer Membervariablen zurück. Wie kann das dazu führen, dass ein ganzes objekt gelöscht wird??
--
MFG RedEagle
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
31.12.2007, 00:05 Uhr
xXx
Devil


? Also ich sehe da immer:

C++:
CFGITEM operator[](string itm);
.
=>
C++:
CFGITEM& operator[](std::string const& item);
CFGITEM const& operator[](std::string const& item) const;
und schon wird nix kopiert!
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
31.12.2007, 01:51 Uhr
Kest
saint



Zitat von RedEagle:
Ich derefenziere ja nichts, ich möchte nicht den Wert zurückgeben, auf den der Zeiger zeigt, sondern den Zeiger selber - also nur einen normalen Wert (bzw eine Adresse)

Richtig. Aber die Frage lautet, was willst du eingentlich mit einer Adresse anfangen, auf der nichts liegt? Sie ist halt nichts anderes als >char* ptr = reinterpret_cast<char*>(std::rand());<.

Zitat von RedEagle:
Ich gebe doch nur den Wert einer Membervariablen zurück. Wie kann das dazu führen, dass ein ganzes objekt gelöscht wird??

Weil dieses Objekt temporär ist.
--
Wenn man einen Hufschlag hört, sollte man >Pferd< denken und nicht >Zebra<.

Dieser Post wurde am 31.12.2007 um 02:02 Uhr von Kest editiert.
 
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: