Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

killmichnich

unregistriert

1

27.08.2010, 10:41

Speicherleck, nur wo?

Hiho,
ich hab bei meinem Programm ein "kleines" Speicherleck entdeckt und weiß nicht genau, wodurch es entsteht. Ich konnte das ganze jedoch auf meine Mesh-Klasse einschränken. Ich hab testweise Meshs erzeugt und gelöscht, und nach 500 mal erzeugen/löschen hab ich ca. 50k mehr Speicher belegt =(
Bei der Meshklasse selber gebe ich eigtl. im Destruktor alle Resourcen frei, hier mal die wichtigen Ausschnitte:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
class CMesh
{
    public:
    CMesh();
    ~CMesh();

    bool Create(string mesh);

    void Draw();

    void ComputeRot(D3DXVECTOR3 rot);

    void SetPosition(D3DXVECTOR3 pos);
    void SetRotation(D3DXVECTOR3 rot);
    void SetScaling(D3DXVECTOR3 sca);
    void Move(D3DXVECTOR3 pos);
    void Rotate(D3DXVECTOR3 rot);
    void Scale(D3DXVECTOR3 sca);

    D3DXVECTOR3 GetRotation();
    D3DXVECTOR3 GetPosition();
    D3DXVECTOR3 GetScaling();

    private:
    static CDirect3D* Direct3D;
    static CLog* Log;

    D3DXVECTOR3 Position;
    D3DXVECTOR3 Rotation;
    D3DXVECTOR3 Scaling;
    D3DXVECTOR3 CRot;

    LPD3DXMESH Mesh;
    DWORD NumMaterials;
    D3DMATERIAL9* Materials;
};


CLog* CMesh::Log = CMesh::Log->GetInstance();
CDirect3D* CMesh::Direct3D = CMesh::Direct3D->GetInstance();

CMesh::CMesh()
{
    Mesh = NULL;
    NumMaterials = NULL;

    Position = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
    Rotation = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
    Scaling = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
    CRot = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
}
CMesh::~CMesh()
{
    if(Mesh)
    {
        Mesh->Release();
        Mesh = NULL;
        delete Materials;
        Materials = NULL;
    }
}

bool CMesh::Create(string mesh)
{
    LPD3DXBUFFER badjacency;
    LPD3DXBUFFER bmaterials;
    LPD3DXBUFFER beffectinstances;

    string cmesh;
    for(int i=0; i<mesh.length()-1; i++)
    {
        cmesh+=mesh[i];
    }

    HRESULT hr = D3DXLoadMeshFromX(mesh.c_str(), D3DXMESH_MANAGED, Direct3D->Device, &badjacency, &bmaterials, &beffectinstances, &NumMaterials, &Mesh);
    if(hr!=D3D_OK)
    {
        Log->Write("Mesh", "Fehler beim Laden eines des Mesh!");
        if(hr==D3DERR_INVALIDCALL)
        {
            Log->Write("Mesh", "Invalid Call!");
        }
        else if(hr==E_OUTOFMEMORY)
        {
            Log->Write("Mesh", "Out of Memory!");
        }
        else
        {
            Log->Write("Mesh", "Keins von beidem!!");
        }
        return false;
    }
    D3DXMATERIAL* materials = (D3DXMATERIAL*)bmaterials->GetBufferPointer();
    Materials = new D3DMATERIAL9[NumMaterials];

    for(int i=0; i<NumMaterials; i++)
    {
        Materials[i] = materials[i].MatD3D;
    }
    return true;
}

Ich dachte eigtl. das im Konstruktor würde genügen, aber dem is anscheinend doch nicht so ^^

Was muss ich denn noch "freigeben", damit kein zusätzlicher Speicher geschluckt wird?

MfG Killmichnich

2

27.08.2010, 10:55

Nach kurzem Überfliegen des Codes:

Materials ist z.B. ein Array, freigegeben wird aber nur das erste Element. delete statt delete[]
Würde den restlichen Code mal daraufhin prüfen.
fka tm

CBenni::O

1x Contest-Sieger

Beiträge: 1 145

Wohnort: Stuttgart

  • Private Nachricht senden

3

27.08.2010, 11:08

Ein Tipp: verwende std::auto_ptr oder tr1::shared_ptr sowie RAII; dann sparst du dir den ganzen Stress. Es lohnt sich wirklich!

mfg CBenni::O
Ein Mitglied der VEGeiCoUndGraSonMaWiGeS Bewegung.
42!
Aufräumen kann jeder, nur das Genie überblickt das Chaos!
Metal will never die!
1. Sppro Gamecontest - mein Beitrag

killmichnich

unregistriert

4

27.08.2010, 11:28

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
CMesh::~CMesh()
{
    if(Mesh)
    {
        Mesh->Release();
        Mesh = NULL;
        delete [] Materials;
        Materials = NULL;
    }
}

Hab ich jetzt mal so eingefügt.
Dann hab ich noch die Buffer in der Create-Methode mit Release() freigegeben, in der Hoffnung, dass es was bringt ...

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
    LPD3DXBUFFER badjacency;
    LPD3DXBUFFER bmaterials;
    LPD3DXBUFFER beffectinstances;
...
...
...
    badjacency->Release();
    bmaterials->Release();
    beffectinstances->Release();

Dadurch brauchts schon ein bisschen weniger Speicher, aber immer noch zu viel.
Sonst fällt mir da ehrlich nix auf was noch Speicher brauchen könnte ôO
Die oben geposteten Code-Teile sind die einzigen in denen sowas vorkommen könnte, in den restlichen werden nur Werte zugewiesen, da kann eigtl. garnix schief gehen ^^

Zitat

Ein Tipp: verwende std::auto_ptr oder tr1::shared_ptr sowie RAII; dann sparst du dir den ganzen Stress. Es lohnt sich wirklich!
jo danke werd ich mir mal anschaun ^^
wobei ich glaub dass es mir hier nich weiterhelfen würde, oder? ôO

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

5

27.08.2010, 11:53

Was genau bringt dich darauf, dass du da ein Speicherleck hast? - Du holst ja lediglich bei Materials selbst welchen, welchen du aber korrekt (sofern das mit der Abfrage immer korrekt funktioniert) frei.

Du kannst ja mal mit VLD schauen, was der meint. Der sagt dir dann auch genau wo du Speicher hast, der nicht freigegeben wurde.

Das Zeugs, was von DX kommt musst du halt noch seperat betrachten und da gibt dir die DX Debug Ausgabe Auskunft, ob es noch nicht-freigegebenen Speicher gibt. Wenn du bei beidem nichts angeschlagen bekommst, dann hast du kein Speicherleck (zumindest nicht in der ausgeführten Version).

killmichnich

unregistriert

6

27.08.2010, 12:09

wie ich drauf komm dass ich n speicherleck hab?
naja ... normal braucht mein programm 50k speicher, wenn ich jetzt aber n paar meshs lad und wieder lösch sinds aufeinmal 100k ... kleiner unterschied ^^

Aber ich hab das Problem jetzt gefunden: ich hab Vertex und Index Buffer von dem Mesh selber freigegeben, wenn ich das mach bleibt auch nach 1500 Meshs laden/löschen bei 50k Speicher ^^

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

7

27.08.2010, 12:57

Ich würde mich aber nicht auf den Taskmanager verlassen, wenn es darum geht, sondern die genannten Tools benutzen. Ansonsten kann es sein, dass du meinst, dass du ein Problem hast, welches gar nicht existiert.
Die Tools sind nämlich sehr exakt. ;)

killmichnich

unregistriert

8

27.08.2010, 13:10

hmm ok thx schau ich mir mal an ^^

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

9

27.08.2010, 13:14

Ansonsten besitzt visual c++ einen memleak detector.
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

10

29.08.2010, 19:58

Die Express Edition auch? :o

Werbeanzeige