DX9 - Texturspeicher freigegeben? / Memory still allocated!



  • Hallo zusammen!

    Ich bin gerade dabei, dieses (http://www.directxtutorial.com/Tutorial9/C-Direct3DMeshes/dx9C3.aspx) DirectX Tutorial zu machen. Leider kommt es in der Ausgabe immer zu folgender Ausgabe (gekürzt)

    Direct3D9: :====> ENTER: DLLMAIN(011be6e0): Process Attach: 000008ac, tid=00000f18
    Direct3D9: :====> EXIT: DLLMAIN(011be6e0): Process Attach: 000008ac
    Direct3D9: (INFO) :Direct3D9 Debug Runtime selected.
    Direct3D9: (INFO) :======================= Hal SWVP device selected
    Direct3D9: (INFO) :HalDevice Driver Style 7
    Direct3D9: :BackBufferCount not specified, considered default 1 
    Direct3D9: :Subclassing window 00010792
    Direct3D9: :StartExclusiveMode
    Direct3D9: (INFO) :Failed to create driver indexbuffer
    Direct3D9: (WARN) :Ignoring redundant SetRenderState - 137
    Direct3D9: (WARN) :Ignoring redundant SetRenderState - 7
    Direct3D9: :====> ENTER: DLLMAIN(011be6e0): Process Detach 000008ac, tid=00000f18
    Direct3D9: (INFO) :MemFini!
    Direct3D9: (WARN) :Memory still allocated!  Alloc count = 389
    Direct3D9: (WARN) :Current Process (pid) = 000008ac
    Direct3D9: (WARN) :Memory Address: 00bd4b48 lAllocID=1 dwSize=000047f8, (pid=000008ac)
    Direct3D9: (WARN) :  Stack Back Trace
    Direct3D9: (ERROR) :    [0] : Address 011BE4CB
    Direct3D9: (ERROR) :    [1] : Address 011BE59B
    Direct3D9: (ERROR) :    [2] : Address 011BE440
    Direct3D9: (ERROR) :    [3] : Address 011B2DB4
    Direct3D9: (ERROR) :    [4] : Address 4FD7AF2E
    Direct3D9: (ERROR) :    [5] : Address 00411EE8
    Direct3D9: (ERROR) :    [6] : Address 00411C77
    Direct3D9: (ERROR) :    [7] : Address 00418336
    Direct3D9: (ERROR) :    [8] : Address 0041809D
    Direct3D9: (ERROR) :    [9] : Address 7C816FD7
    Direct3D9: (ERROR) :    [10] : Address 00000000
    Direct3D9: (ERROR) :    [11] : Address 00000000
    Direct3D9: (ERROR) :    [12] : Address 00000000
    Direct3D9: (ERROR) :    [13] : Address 00000000
    Direct3D9: (ERROR) :    [14] : Address 00000000
    Direct3D9: (ERROR) :    [15] : Address 00000000
    
    [...hier wiederholen sich die letzten 18 Zeilen fast exakt]
    
    Direct3D9: (WARN) :Total Memory Unfreed From Current Process = 2551517 bytes
    Direct3D9: :====> EXIT: DLLMAIN(011be6e0): Process Detach 000008ac
    Das Programm "[2220] tutorial_vc++05pro.exe: Systemeigen" wurde mit Code 0 (0x0) beendet.
    

    Nun habe ich folgendes Tutorial (http://www.directxtutorial.com/Tutorial9/C-Direct3DMeshes/dx9C2.aspx) auch einmal compiliert und hier treten die Fehler nicht auf. Es werden auch keine Texturen benutzt, so dass ich vermutet habe, dass einfach der Speicherplatz der Texturen im erstgenannten Tutorial nicht freigegeben wird und somit die oben genannten 'memory leaks' auftreten.

    Hier ist der Code, der die Ressourcen eigentlich freigeben sollte:

    void cleanD3D(void)
    {
      meshSpaceship->Release();  // close and release the spaceship mesh
      d3ddev->Release();         // close and release the 3D device
      d3d->Release();            // close and release Direct3D
      return;
    }
    

    Allerdings wird das D3D Device doch freigegeben, somit sollte doch auch der Speicherplatz der Texturen freigegeben sein.

    Nun direkt meine Fragen:
    - Muss der Texturenspeicher einzeln wieder freigegeben werden oder nicht?
    - Sieht jemand auf Anhieb einen Fehler oder ist das, was mir die Ausgabe liefert sogar ein gewünschtes Ergebnis?

    Vielen Dank schonmal im Voraus!



  • iop schrieb:

    Allerdings wird das D3D Device doch freigegeben, somit sollte doch auch der Speicherplatz der Texturen freigegeben sein.

    Das ist eine Fehlannahme. Sinnvolle wäre es natürlich, wenn du dir einen Resourcen-Manager schreibst, der genau das macht.



  • Man muss sich also doch selbst darum kümmern. Danke erstmal - ich kam nur auf die Idee, dass man es nicht muss, weil der für die Texturen verwendete Speicher nicht nur in diesem Tutorial, sondern auch im "Two Kings" Tutorial nicht wieder freigegeben wurde.

    Jetzt habe ich noch eine Frage zum Freigeben. Und zwar habe ich schon versucht, die Texturen mit diesem Befehl zu löschen:

    delete []texture;
    

    Das ändert aber nix an den Leaks, und ich weiß noch nichteinmal, ob das so stimmt. Ich bin mir jedenfalls nicht sicher, da "texture" vom Typ LPDIRECT3DTEXTURE9* ist, was ja an sich schon ein Zeiger ist (wenn ich das richtig verstanden habe). Ist der Code zum Löschen also so richtig?

    ..ich habe mir bisher einige Sachen zum Thema "dynamische Speicherreservierung" angeguckt (unter anderem auch hier im Forum: http://www.c-plusplus.net/forum/viewtopic-var-t-is-39497.html), aber wie gesagt, ich bin mir nicht sicher.



  • Das Ding hat auch ne Release()-Funktion, die musst du benutzen denn sie gibt Speicher auf der Grafikkarte frei. Delete gibt Speicher in deinem Heap frei, den du vorher mit new allokiert hast. Das sind zwei völlig verschiedene Dinge.



  • Ja, das hatte ich auch gesehen und auch mal so versucht (funktioniert leider gar nicht):

    DWORD i;
    for(i=0;i<=numMaterials;i++)
    {
      if(texture[i]!=NULL)
      texture[i]->Release();
    }
    

    Nur gibt es ja diese Zeile:

    texture = new LPDIRECT3DTEXTURE9[numMaterials];
    

    Hier habe ich doch mit new Speicher auf dem heap allokiert, oder nicht?



  • Ich sag ja nicht, dass dein delete[] falsch war. Ggf. brauchst du es. Aber das Release() brauchst du immer ebenfalls.



  • Ersteinmal vielen Dank für die Antworten!

    Ich habe es jetzt so gemacht, das scheint zu funktionieren. Zumindest sind die "memory leaks" dadurch weniger geworden.

    DWORD i;
    for(i=0;i<numMaterials;i++)
    {
      if(texture[i])
      {
        texture[i]->Release();
        texture[i] = NULL;
      }
    }
    

    Ich verstehe aber leider immer noch nicht, was es hier mit delete und release auf sich hat..

    Generell: Was muss ich denn eigentlich alles releasen?



  • iop schrieb:

    Generell: Was muss ich denn eigentlich alles releasen?

    Alles, was du mit Create[..] erstellt hast 😛

    -> in umgekehrter Reihenfolge natürlich



  • xindon schrieb:

    -> in umgekehrter Reihenfolge natürlich

    quark. dann wenn du es nicht mehr brauchst. die reihenfolge ist absolut wurst.



  • otze schrieb:

    xindon schrieb:

    -> in umgekehrter Reihenfolge natürlich

    quark. dann wenn du es nicht mehr brauchst. die reihenfolge ist absolut wurst.

    Fuer manche Sachen ist es chon sinnvoll, die Reihenfolge einzuhalten. Wenn ich z.b. erst ein Device erzeuge, dann mit dem Device eine Texture und mir dann einen der Mip-Level aus der Textur hole.

    Im Grunde kann man aber auch einfach den Prozess beenden, dann wird auch alles freigegeben. f'`8k

    Autocogito

    Gruß, TGGC (making great games since 1992)



  • Ja, so habt ihr es bei Anno gemacht, oder? 😉



  • Nochmals zuallererst vielen Dank für die zahlreichen Antworten!

    Ich habe es jetzt so gemacht und es funktioniert (ich poste es mal, eventuell für andere Anfänger):

    #define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p);   (p)=NULL; } }
    #define SAFE_RELEASE(p)      { if(p) { (p)->Release(); (p)=NULL; } }
    #define SAFE_DELETE(p)       { if(p) { delete (p);     (p)=NULL; } }
    
    void cleanD3D(void)
    {
      DWORD i;
      for(i=0;i<numMaterials;i++)
      {
        SAFE_RELEASE(texture[i]);
        SAFE_RELEASE(t_buffer);
        SAFE_RELEASE(z_buffer);
      }
    
      SAFE_RELEASE(meshSpaceship);
      SAFE_RELEASE(d3ddev);
      SAFE_RELEASE(d3d);
    
      SAFE_DELETE_ARRAY(texture);
      SAFE_DELETE_ARRAY(material);
      SAFE_DELETE(t_buffer);
      SAFE_DELETE(z_buffer);
      SAFE_DELETE(meshSpaceship);
      SAFE_DELETE(d3ddev);
      SAFE_DELETE(d3d);
    
      return;
    }
    

    Eine Frage habe ich aber noch zum Material. Es ist ganz egal, ob ich den Pointer freigebe oder nicht, es tauchen keine Memory Leaks mehr auf. Aber ich habe doch dynamisch Speicher auf dem Heap reserviert:

    material = new D3DMATERIAL9[numMaterials];
    

    Müsste da nicht auch eine Fehlermeldung kommen?



  • Optimizer schrieb:

    Ja, so habt ihr es bei Anno gemacht, oder? 😉

    Noe, aber in meinen 4k Intros. Da muss man ja auch nicht zwischendurch die Auefloesung wechseln. Moment mal, manche Spiele muessen auch dafuer neu starten... f'`8k

    Gruß, TGGC (making great games since 1992)



  • Die ganzen D3D Ressourcen wie Device, Texturen etc. muss man doch "releasen" und nicht "deleten", oder? (wegen SAFE_DELETE(d3d); in iops sourcecode)



  • this->that schrieb:

    Die ganzen D3D Ressourcen wie Device, Texturen etc. muss man doch "releasen" und nicht "deleten", oder? (wegen SAFE_DELETE(d3d); in iops sourcecode)

    Hm, stimmt, SAFE_DELETE(d3d) ist hier überflüssig, es ist mit d3d ja kein Speicher auf dem Heap allokiert worden, richtig?! Da war ich wohl übermütig 🙂



  • iop schrieb:

    Hm, stimmt, SAFE_DELETE(d3d) ist hier überflüssig, es ist mit d3d ja kein Speicher auf dem Heap allokiert worden, richtig?!

    Genau.
    Eine Frage, weil ich mir nimmer sicher bin: Wenn ich ne D3D Ressource anlege, zB nen VB mit CreateVertexBuffer, dann hab ich in ppVertexBuffer nen Pointer auf ein COM Objekt, dessen Referenzzähler bereits auf 1 steht. D.h. wenn ich mit dem VB fertig bin, muss ich einmal Release aufrufen? (RefCount=0, Objekt kann gelöscht werden).
    Wann wird eigentlich der interne Reference Counter erhöht? Da ich ja immer genau so oft Release() aufrufen muss wie der interne Reference Counter, muss ich mir ja irgendwo merken auf welchem Wert der RefCounter gerade steht, oder?



  • *push.

    Weiß das denn wirklich niemand? 😞



  • Ich verstehe die Frage nicht ganz. Zu einem create gehoert ein Release, ganz einfach. Egal wie der Ref Counter ist. Erhoert wird der Counter, wenn die Resource durch irgendwas referenziert wird. Darum ist ja auch die Reihenfolge nicht so wichtig beim Releasen, der Ref Counter sorgt zur Not dafuer, dass ein zu frueh releastes Objekt nicht direkt zerstoert wird. f'`8k

    Autocogito

    Gruß, TGGC (making great games since 1992)



  • Ich wiederhole meine Frage einfach nochmal:
    Wann wird der Reference Counter erhöht? Klar durch AddRef(), aber das wird man selber ja wohl nie benutzen. Hat da jemand mal ein konkretes Beispiel zB für ne Textur oder nen VB?



  • this->that schrieb:

    Ich wiederhole meine Frage einfach nochmal:
    Wann wird der Reference Counter erhöht? Klar durch AddRef(), aber das wird man selber ja wohl nie benutzen. Hat da jemand mal ein konkretes Beispiel zB für ne Textur oder nen VB?

    Ich habs zwar eben schon gesagt, aber hier nochmal die Antwort aus der Doku:

    reference count:
    Control for a COM object. When an object is created, its reference count is set to 1. Every time an interface is bound to the object, its reference count is incremented; when the interface connection is destroyed, the reference count is decremented. The object is destroyed when the reference count reaches 0. All interfaces to that object are then invalid.

    f'`8k

    Gruß, TGGC (making great games since 1992)


Anmelden zum Antworten