shared_ptr - Delete?
-
Eisflamme schrieb:
Jedenfalls gibt es da was zu tun.
Das ist der Plan. Das programm läuft Absturzsicher und macht keine Probleme, nur ich will a) die Leaks loswerden denn das kann vermutlich zu einem Problem werden, und b) "unsauberen" code durch "besseren" ersetzen.
Den Ansatz das raw pointer schlecht sind hab ich mitlerweile verworfen.
Ich werd hier nochmal alles durchlesen und versuchen alle Tipps anzuwenden.
-
cl90 schrieb:
Ok, Ich habe vorher mit Raw Pointer gearbeitet. Mir wurde nur abgeraten das weiter zu machen.
Das Problem sind nicht die Raw-Pointer, das Problem sind Raw-Pointer in Verbindung mit
new
. Denn bei denen musst du manuelldelete
aufrufen. Raw-Pointer, die auf ein Objekt zeigen, welches an anderer Stelle verwaltet wird (z.B. durch Smart-Pointer, oder weil es auf dem Stack liegt) sind kein Problem.
-
Das Problem ist, das man hier Anfängern shared_ptr und Konsorten um die Ohren haut, bevor sie überhaupt verstanden haben, was das Problem ist.
-
Das Problem ist, das man hier Anfängern shared_ptr und Konsorten um die Ohren haut, bevor sie überhaupt verstanden haben, was das Problem ist.
Also müssen sie erst verstehen, dass das Problem ist, dass man hier Anfängern shared_ptr und Konsorten um die Ohren haut, bevor sie überhaupt verstanden haben, was das Problem ist.
-
Im Prinzip ist die Geschichte mit automatisch delete aufrufen relativ überflüssig, wenn keine Exceptions im Spiel sind. Denn dann ist es noch überschaubar, an welchen Stellen Speicher deletet werden muss. Das bedeutet nicht, dass das dann schön ist oder keinerlei Fehler(Memory Leaks) auftreten können, aber in der Theorie würde das reichen.
Sobald aber Exceptions dazukommen geht die Ressourcen-Verwaltung nur noch sinnvoll und übersichtlich mit RAII.
Daher, vllt anfangs mal 2-3 Übungen machen mit new+delete, danach alles in RAII-Klassen einkapseln!
-
Ja ich versteh ja auch euren Standpunkt. Nur leider ist es an meiner Uni so das die Profs sich nicht darum scheren woher du die Sprache kennst, du sollst nur Ihre Projekte machen können. Das Man dann nicht die Zeit hat sich ein gutes Buch zur Hand zu nehmen und bei 0 Anzufangen ist leider vorprogrammiert.
Ich bin auch direkt eingestiegen, und hab mich durch Trial and Error "Weiterentwickelt". Und solche Grundlagen fehlen dann leider manchmal.Die ganzen Pointer/shared_ptr sachen waren übrigents gar nicht das Problem...
Das Problem liegt in der Allokierung der DirectX Ressourcen. Texturen und Meshes... Ich muss mich jetzt erstmal einlesen wie die Strukturen aufgebaut sind damit ich weiß wie ich die wieder löschen kann.
-
DirectX verwendet COM Objekte.
Löschen tut man diese nicht, man gibt nur "seine" Referenz auf sie frei. Und wenn das die letzte Referenz war, dann löscht sich das Objekt von selbst.Zum Referenz-Zählen verwendet man ->AddRef() und ->Release(). Bzw. spezialisierte Smart-Pointer Klassen die einem das abnehmen.
-
Skym0sh0 schrieb:
Im Prinzip ist die Geschichte mit automatisch delete aufrufen relativ überflüssig, wenn keine Exceptions im Spiel sind. Denn dann ist es noch überschaubar, an welchen Stellen Speicher deletet werden muss. Das bedeutet nicht, dass das dann schön ist oder keinerlei Fehler(Memory Leaks) auftreten können, aber in der Theorie würde das reichen.
Sobald aber Exceptions dazukommen geht die Ressourcen-Verwaltung nur noch sinnvoll und übersichtlich mit RAII.
Daher, vllt anfangs mal 2-3 Übungen machen mit new+delete, danach alles in RAII-Klassen einkapseln!
Wenn Exceptions im Spiel sind, dann erleichtern RAII und Smartpointer das Leben ungemein. Wenn keine Exceptions verwendet werden, dann erleichtern sie nur ein wenig, aber sie tun es doch. Also warum sollte man auf RAII und Smartpointer verzichten? Wobei ich mich auch frage, warum man auf Exceptions verzichten sollte.
Wobei auch ohne Exceptions gibt es genügend Möglichkeiten, die Freigabe von Resourcen zu übersehen. Also nehme ich es zurück, dass RAII und Smartpointer ohne Exceptions das Leben nur ein wenig erleichtern. Sie tun es auch ohne Exceptions ungemein
.
-
tntnet schrieb:
Wobei auch ohne Exceptions gibt es genügend Möglichkeiten, die Freigabe von Resourcen zu übersehen.
Wer geschickt programmiert, für den ist das auch ohne RAII übersichtlich (ohne Exceptions).
10-Zeilen-Funktionen + Ressourcenmanagement von Verarbeitung trennen = übersichtlicher Code.
-
Nur ist das Problem, dass RAII schon vom Design her Fehler vermeidet. Programmierer sind Menschen, das heißt sie machen Fehler. Und das heißt, auch ihr Code tendiert zu Fehlerhaftigkeit. RAII macht es schwerer, Fehler zu machen. Es kann neue hervorrufen, aber eine noch größere Reihe von Fehlern wird damit behoben.
-
öhm...
Mag mir das jemand erklären:void main() { // Erzeugt leaks CData data = CData(); } void main() { // Erzeugt keine leaks CData data(); } void main() { // Erzeugt keine leaks CData* data = new CData(); delete data; } // jetzt ein Konstruktor einer Klasse: DirectX_Device :: DirectX_Device(CData* cdata) { // Erzeugt leaks. m_xfiles.push_back("plate.x"); m_xfiles.push_back("lowPolySphere.x"); } DirectX_Device :: DirectX_Device(CData* cdata) { // Erzeugt Keine leaks. //m_xfiles.push_back("plate.x"); //m_xfiles.push_back("lowPolySphere.x"); }
Das mit "data = CData()" ist mir neu..
Und muss man Vectoren deleten?
-
void main() { // Erzeugt leaks CData data = CData(); }
Das kann gar nichts, denn es ist kein gültiges C++.
Und selbst wenn du den Rückgabetyp zuint
änderst, ist diese Variante genauso sicher wie die zweite.Und muss man Vectoren deleten?
Nein. Deswegen sind sie u.a. so angenehm.
-
cl90 schrieb:
void main() { // Erzeugt leaks CData data = CData(); }
Das sollte keine Leaks erzeugen. Vermutlich gibt es einen Bug im Copy-Konstruktor von
CData
. Das würde auch erklären, warum der Fall mitnew
keine Leaks erzeugt, denn dort wird nur der normale Konstruktor aufgerufen.Nebenbei: im zweiten Fall wird kein
CData
-Objekt angelegt, sondern eine Funktion ohne Parameter mit RückgabewertCData
deklariert. Was du vermutlich willst, istCData data; // ohne ()
Vermutlich erzeugt das auch keine Leaks, aus dem gleichen Grund wie im
new
-Fall.
-
ipsec schrieb:
cl90 schrieb:
void main() { // Erzeugt leaks CData data = CData(); }
Das sollte keine Leaks erzeugen. Vermutlich gibt es einen Bug im Copy-Konstruktor von
CData
.Deshalb erzeugt auch das push_back() Leaks, hast die Klasse kein Move und gibt der Copykonstruktor vorher erzeugte Handles oder was auch immer nicht frei, gibts bei jeder Kopie Leaks.
-
also:
CData data;
Erzeugt auch leaks.
Aber ich habe nur einen Konstruktor deklariert. Ich hab mit dem Copy Konstruktor nichts gedreht.
CData sieht so aus:
class CData { public: CData(); // Sehr viele Funktionen nach Muster get/set D3DXVECTOR3* get_TargetPtr(int leg); // bsp. private: // Die Entsprechenden Variablen zu get/set int m_ReadDelay; //bsp. }; CData :: CData() : m_UDPSocket(&m_Acceleration, &m_RollPitchYaw), m_CIni() // Erzeugt auch ohne die beiden Klassen Leaks. // Ich geh also davon aus das die ok sind. { // initialisierungen. Alles ohne new }
-
void main() { // Erzeugt leaks CData data = CData(); }
Dann erzeugt dieser Code-Schnipsel dadurch Leaks, dass der Konstruktor von CData aufgerufen wird...
-
Zeig doch Mal mehr von der Klasse.
Ich kann mir vorstellen, dass die Regel der großen 3 (5) nicht eingehalten wurde, d.h. es gibt einen dtor, der irgendwo
delete
aufruft, jedoch sind operator= und copy-ctor eben nicht definiert. Das führt dann dazu, dass der referenzierte Speicher gelöscht wird.Oder heißt Leaks, dass irgendwas nicht freigegeben wird? Eigentlich würde das Programm ja dann ziemlich klar crashen, wenn meine Theorie oben stimmen würde.
Kann auch sein, dass einfach das delete zum jeweiligen new fehlt, wenn weder copy-ctor, operator= noch dtor definiert sind, aber in ctor new aufgerufen wird.
Eins von beidem wird's doch wohl sein, komm schon.
-
Ok. Also dann werde ich mal mehr Posten damit ihr euch ein größeres Bild machen könnt.
denn CData hat jetzt grade zum leak finden absolut keinen inhalt:
CData :: CData() //: m_UDPSocket(&m_Acceleration, &m_RollPitchYaw), // m_CIni() { /*unsigned int i; // Ctrl /////////////////////////////////////////////////////////////////////////// m_mouseL = false; m_mouseR = false; m_wheel = 0.0f; m_X = 400; m_Y = 400; m_WASD_Toggle = 1; m_Toggle = false; for(i = 0; i < 256; i++) m_keystate[i] = false; m_Acceleration = D3DXVECTOR3(0, 0, 0); m_RollPitchYaw = D3DXVECTOR3(0, 0, 0); // Console /////////////////////////////////////////////////////////////////////////// m_wireframe = false; // View /////////////////////////////////////////////////////////////////////////// m_viewDistance = 50.0f; m_viewRotHori = 0; m_viewRotVert = 0; // Leg /////////////////////////////////////////////////////////////////////////// m_Length[0] = 3.29f; m_Length[1] = 1.5f; m_Length[2] = 6.78f; m_Length[3] = 8.07f; D3DXMatrixRotationZ (&m_matRot90, D3DXToRadian(-90)); D3DXMatrixScaling (&m_matBodySize, 0.1f, 0.1f, 0.1f); D3DXMatrixScaling (&m_matAxisSize, 0.05f, 2.0f, 0.05f); D3DXMatrixRotationY (&m_matTurn, D3DXToRadian(180)); D3DXMatrixTranslation (&m_matTransSO, -m_Length[0], 0, 0); D3DXMatrixTranslation (&m_matTransVS, 0, m_Length[1], 0); D3DXMatrixTranslation (&m_matTransOS, 0, m_Length[2], 0); D3DXMatrixTranslation (&m_matTransUS, 0, m_Length[3], 0); // General /////////////////////////////////////////////////////////////////////////// m_KillThisProcess = false; m_ReadDelay = 0;*/ }
Das Hauptprogramm sieht in wirklichkeit auch so aus:
CData ist global. (weil ich es auch für Windowproc nutzen wollte.)// includes CData data = CData(); //CData* data = new CData(); //CData data; //DirectX_Device dxdv(&data); #include "inc/win_api.h" int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { //delete data; _CrtDumpMemoryLeaks(); return EXIT_SUCCESS; }
-
Ist da wirklich alles auskommentiert und das liefert dann immer noch Leaks? (in der CData-Klasse?)
Falls ja, gibt es auch statische Member von CData? Falls nein, würde ich natürlich auch die Klassen prüfen, deren Instanzen Member von CData sind.
Gerne kannst Du auch Mal die CData-Schnittstelle (Header) zeigen, man weiß ja nie.
-
Eisflamme schrieb:
Oder heißt Leaks, dass irgendwas nicht freigegeben wird?
lol