Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Assertion Failed beim Lösen von Variablen

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
21.06.2010, 18:43 Uhr
Hellcat



Ich habe ein Probelm, daß ich mir nicht so ganz erklären kann. Jedes Mal, wenn ich die Methode DeleteAll aufrufe, erhalte ich eine "Assertion Failed" Message, unabhängig davon, ob der Vektor mit gültigen Werten gefült ist oder nicht. Der gleiche Code läuft in der Methode Delete einwandfrei. Kann mir da jemand weiterhelfen?


C++:
void Delete(const T p)
            {
                for (unsigned int i = 0; i < size(); i++)
                {
                    if (Equals (at(i), p))
                    {
                        T &tmp = at(i);
                        delete &tmp;                        
                        erase(begin()+i);
                        break;
                    }
                }
                return;
            }



C++:
void DeleteAll()
            {
                for (unsigned int i = size()-1; i >= 0; i--)
                {
                        T &tmp = at(i);
                        delete &tmp;                        
                        erase(end()-1);
                }
                return;
}



C++:
static int TestDelete()
            {
                cout <<"VectorSecure::TestDelete" << endl;
                VectorSecure<int*> vi;
                int* pI1 = new int;

                *pI1 = 0;

                vi.push_back(pI1);
                vi.Delete(pI1);

                cout << "c = " << vi.size() << endl;

                return 0;

            }



C++:
static int TestDeleteAll()
            {
                cout <<"VectorSecure::TestDeleteAll" << endl;
                VectorSecure<int*> vi;
                int* pI1 = new int;
                *pI1 = 1;
                int* pI2 = new int;
                *pI1 = 2;
                int* pI3 = new int;
                *pI1 = 3;

                vi.push_back(pI1);
                vi.push_back(pI2);
                vi.push_back(pI3);

                vi.DeleteAll();

                cout << "c = " << vi.size() << endl;

                return 0;
}

Dieser Post wurde am 21.06.2010 um 18:43 Uhr von Hellcat editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
21.06.2010, 20:40 Uhr
0xdeadbeef
Gott
(Operator)



C++:
for (unsigned  int i = size()-1; i >= 0; i--)


Wenn i == 0, was passiert da?
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
21.06.2010, 22:48 Uhr
Hellcat



Ich hätte jetzt gesagt er geht in die Schleife, aber wenn du schon so fragst scheint da ein Denkfehler meinerseits vorzuliegen...

Unabhängig davon tritt der Fehler aber bei i == 2 auf, also deutlich vorher.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
22.06.2010, 09:18 Uhr
Hellcat



Ok, ich hab noch mal ein wenig ausprobiert und festgestellt, daß die Funktion Delete auch nicht richtig funktioniert. Sobald ich einen weiteren Wert in den Vektor packe und den ersten Wert dann lösche werden die folgenden Pointer auf den Wert 0xfeeefeee gesetzt.
Irgendwas muss also an dem Aufruf

C++:
delete &tmp;

falsch sein, aber was?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
22.06.2010, 09:58 Uhr
0xdeadbeef
Gott
(Operator)


&tmp gibt dir die Adresse von tmp im Speicher, also die Adresse des Zeigers, der auf das zeigt, was du löschen willst. Beim ersten Element ist das wahrscheinlich der Datenbereich des Vektors, und womöglich verhält sich delete bei deinem Compiler wie delete[] - im Standard ist das Verhalten solcher Scherze natürlich undefiniert.

Versuch's mal mit

C++:
delete tmp;


oder gleich

C++:
delete at(i);


--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
22.06.2010, 10:53 Uhr
Hellcat



So, ich hab meinen Code noch mal ein wenig umgebaut (danke an 0xdeadbeef für den Hinweis).

C++:
void Delete(const  T p)
            {
                for (unsigned int i = 0; i < size(); i++)
                {
                    if (Equals (at(i), p))
                    {
                        T tmp = at(i);
                        erase(begin()+i);
                        delete tmp;                        
                        break;
                    }
                }
                return;
            }

Allerdings stehe ich jetzt vor dem Problem, daß der Compiler einen C2541 ausgibt, weil tmp auch mal kein Pointer sein kann (das ganze ist eine Template-Funktion). Jetzt ist die Frage, wie ich das Problem umgehen kann. Spezialisiung des Templates wäre eine Variante, allerdings sollte das nach Möglichkeit nicht so gelöst werden. Kann mir da jemand weiterhelfen?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
22.06.2010, 11:12 Uhr
0xdeadbeef
Gott
(Operator)


Wenn's kein Zeiger ist, kannst du's nicht in delete schmeißen.

Das ganze ist ein bisschen eine Designfrage. Natürlich kann man prinzipiell etwas wie

C++:
template<typename T> void remove_from_heap(T) { }
template<typename T> void remove_from_heap(T* p) { delete p; }

// ...

T tmp = at(i);
erase(begin() + i);
remove_from_heap(tmp);


machen, aber es scheint mir etwas gewagt, einen Container zu bauen, der abhängig vom Werttyp versucht, seine Daten vom Heap zu löschen - meines Erachtens wärst du mit zwei verschiedenen Typvorlagen oder einer Strategy-Pattern besser dran. Dieser Plan kann dir böse in die Hose gehen, wenn du nicht sehr deutlich kommunizierst, dass und warum

C++:
VectorSecure<int> vi;
VectorSecure<int*> vp;

int x = 2;

vi.push_back(x);
vi.push_back(&x);


nicht vorgesehen ist. Oder auch

C++:
VectorSecure<int*> vp;

vp.push_back(new int[10]); // Ups.


--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 22.06.2010 um 11:13 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
22.06.2010, 11:53 Uhr
Hellcat




Zitat von 0xdeadbeef:
Wenn's kein Zeiger ist, kannst du's nicht in delete schmeißen.

Das ist mir klar, deswegen brauche ich irgendwas in der Art:

C++:
if (vom Typ Pointer)
{
  T tmp = at(i);
  erase(begin() + i);
  delete tmp;
}
else
{
  Mach was anderes
}


Hab aber keinen blassen Schimmer wie ich das mit Templates vernünftig umsetzen kann...


Zitat von 0xdeadbeef:
meines Erachtens wärst du mit zwei verschiedenen Typvorlagen oder einer Strategy-Pattern besser dran.

Das ist mir auch klar, nur leider ist die Aufgabenstellung so, daß weder eine Spezialisierung (wie in deinem Vorschlag) noch irgendein Designpattern in Frage kommt.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
22.06.2010, 13:15 Uhr
0xdeadbeef
Gott
(Operator)


Ohne Spezialisierung sehe ich da keine Möglichkeit - wenn du das für alle Typen in einen Funktionskörper quetschen muss, muss der gesamte Funktionskörper durch den Compiler, und der frisst in dem Zusammenhang halt nur Zeiger.

Das Ganze klingt nach einer ziemlich dämlichen Aufgabenstellung. Was bringen die euch denn da bei?
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
22.06.2010, 13:22 Uhr
Hellcat



Oh mann, C++ macht mich fertig...

Ich hab's mal mit Spezialisierung ausprobiert, da es ja anscheinend nich anders geht. Somit habe ich die folgenden beiden Funktionen:

C++:
void Delete(const T p)
void Delete(const T* p)

Meine Testfunktion sieht so aus, daß ich ein vector von Pointern (in diesem Fall auf int) erzeuge und ihn mit entsprechenden Zeigern fülle:

C++:
            static int TestDelete()
            {
                cout <<"VectorSecure::TestDelete" << endl;
                VectorSecure<int*> vi;
                int* pI1 = new int;

                *pI1 = 0;

                int* pI2 = new int;

                *pI2 = 1;

                vi.push_back(pI1);
                vi.push_back(pI2);

                vi.Delete(pI1);

                cout << "c = " << vi.size() << endl;

                return 0; //TODO Testauswertung schreiben

            }


Nach meinem Verständnis müsste er in die Delete(const T* p) springen, er springt aber in
void Delete(const T p). Das ist für mich irgendwie nicht nachvollziebar...

@edit: ich hab's gefunden, Spezialisierung geht nur mit Klassen...


Zitat von 0xdeadbeef:
Was bringen die euch denn da bei?

Frag nicht...

Dieser Post wurde am 22.06.2010 um 13:28 Uhr von Hellcat 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: