2010-07-04 4 views
1

J'ai une classe ici qui est défini comme ceci:vous aider à identifier la mémoire fuites

struct USERFPOINT 
{ 
    POINTFLOAT UserPoint; 
    POINTFLOAT LeftHandle; 
    POINTFLOAT RightHandle; 
    bool isBezier; 
}; 

struct SHAPEOUTLINE { 
    GLuint OutlineVBO; 
    int OutlineSize; 
    int OutlineWidth; 
    ARGBCOLORF OutlineColor; 
}; 

struct SHAPECONTOUR{ 

    std::vector<USERFPOINT> UserPoints; 
    std::vector<std::vector<GLdouble>> DrawingPoints; 
    SHAPEOUTLINE Outline; 

}; 
struct SHAPEGRADIENT{ 
    GLuint TextureId; 
    bool IsParent; 
    bool active; 
    int type; 
    std::vector<ARGBCOLORF> colors; 
}; 

struct SHAPEDIMENSIONS { 
    POINTFLOAT Dimensions; 
    POINTFLOAT minima; 
    POINTFLOAT maxima; 
}; 

class OGLSHAPE 
{ 
private: 
    int WindingRule; 
    GLuint TextureCoordsVBOInt; 
    GLuint ObjectVBOInt; 
    UINT ObjectVBOCount; 
    UINT TextureCoordsVBOCount; 
    SHAPEGRADIENT Gradient; 
    SHAPEDIMENSIONS Dimensions; 
    void SetCubicBezier(USERFPOINT &a,USERFPOINT &b, int &currentcontour); 

    void GenerateLinePoly(const std::vector<std::vector<GLdouble> > &input, int width); 
public: 
    std::string Name; 
    ARGBCOLORF MainShapeColor; 
    std::vector<SHAPECONTOUR> Contour; 
    OGLSHAPE(void); 

    void UpdateShape(); 
    void SetMainColor(float r, float g, float b, float a); 
    void SetOutlineColor(float r, float g, float b, float a,int contour); 
    void SetWindingRule(int rule); 
    void Render(); 
    void Init(); 
    void DeInit(); 
    ~OGLSHAPE(void); 
}; 

Voici ce que je l'ai fait comme un test. J'ai créé un test global std::vector<OGLSHAPE>.

Dans la fonction que j'utilisais, j'ai créé

OGLSHAPE t. J'ai ensuite poussé 50 000 copies de t dans le test. J'ai ensuite immédiatement effacé le test et utilisé l'astuce de swap pour vraiment le désallouer. J'ai remarqué que toute la mémoire était correctement libérée comme je m'y attendais. J'ai alors fait la même chose mais avant de pousser t dans test, j'ai poussé un SHAPECONTOUR (que je venais de créer sans rien modifier ou ajouter dans le contour) avant de pousser t dans le test.

Cette fois après le test de libération, 3 mégaoctets de plus ont été alloués. Je l'ai fait encore allouer deux fois plus et maintenant 6MB nous restons. L'utilisation de la mémoire du programme a culminé à 150 Mo et il est descendu à 12 Mo, mais il devrait être à 8,5 Mo. Par conséquent, cela doit être classé comme une fuite de mémoire, même si je ne vois pas comment. Il n'y a rien que je vois qui pourrait faire cela. SHAPECONTOUR est simplement une structure de vecteurs avec une structure imbriquée de vecteurs.

Pourquoi cela causerait-il une fuite, et comment pourrais-je le réparer?

Merci

+2

Essayez valgrind ou un outil similaire. –

+0

Je ne vois pas un seul "nouveau" dans le code que vous avez posté, donc il sera difficile de trouver une "fuite". Utilisez valgrind, mais je pense que vous découvrirez que ce n'est pas une fuite et que l'OS n'a tout simplement pas récupéré la mémoire. – Stephen

+0

En utilisant Windows, valgrind est 4 linux – jmasterx

Répondre

2

Si vous avez supprimé tout, il n'y a pas de fuite, par définition. Je ne vois pas de pointeurs déballés, tout est effacé. Par conséquent, vous n'avez aucune fuite.

Probablement, le système d'exploitation a simplement décidé de laisser cette mémoire disponible pour votre programme, quelle qu'en soit la raison. (Il ne l'a pas "récupéré".) Ou peut-être qu'il a besoin d'allouer en groupes de 4 Mo, et donc passer de 12 Mo à 8 Mo ne laisserait pas assez de mémoire requise. Ou ...

Vous supprimez entièrement d'autres raisons; vous devriez utiliser un véritable outil de fuite de mémoire pour trouver des fuites de mémoire.

+0

+1 à OS ne récupérant pas la mémoire. 'new' alloue de la mémoire à partir d'un pool séparé qui est géré par la bibliothèque d'exécution et' delete 'ne renvoie pas toujours la mémoire libérée immédiatement au système d'exploitation. – casablanca

+0

Est-il normal qu'elle ne le récupère jamais? – jmasterx

+0

@user: Oui. Il est beaucoup plus simple de laisser cette mémoire pour votre programme, car les allocations supplémentaires ne nécessitent pas que le système d'exploitation obtienne une nouvelle page de mémoire pour vous. Si un autre programme a besoin de mémoire et que le système d'exploitation est faible, il vous l'enlèvera. – GManNickG

0

Je suggère d'utiliser un outil de détection de fuite pour savoir si vous avez vraiment une fuite. Par exemple, pour Windows dev, vous pouvez utiliser Visual Leak Detetor (VLD).

Si vous avez effectivement une fuite alors ce n'est probablement pas où vous pensez que c'est.

Vous pouvez également vous tromper en ce qu'il n'y a aucune fuite. Par exemple, si vous regardez juste les statistiques via quelque chose comme le gestionnaire de tâches, cela ne signifie pas qu'il y a une fuite dans votre programme. Le système d'exploitation qui exécute votre programme est une bête distincte du langage de programmation que vous pouvez avoir une fuite à l'intérieur. C'est à dire. le système d'exploitation peut prendre plus de temps pour récupérer la mémoire libérée.

Edit:

Si vous voulez vous assurer que le vector a capacity 0, il est assez fréquent de faire ce qui suit:

v.swap(std::vector<char>()); 
assert(v.capacity() == 0); 
+0

Visual Leak Detector n'a détecté aucune fuite. – jmasterx

+0

Ensuite, vous n'avez probablement pas de fuites. Essayez d'insérer une fuite intentionnellement (utilisez le nouveau sans supprimer) puis vérifiez si elle le détecte pour vous assurer que vous l'utilisez correctement. –

+0

Il a détecté la nouvelle chose, je pense que ce n'est pas une fuite et plutôt le fait que std :: vector ne libère que sur ~ vector. Mais je ne peux toujours pas trouver le coupable responsable ... – jmasterx

0

Que diriez-vous de compensation explicitement les vecteurs de SHAPECONTOUR dans le destructor d'OGLSHAPE? Réexécutez votre test avec ce & vérifiez si vous avez toujours la fuite observée.

0

Comment effacez-vous ces vecteurs? Essayez d'utiliser à quelque chose comme ceci Destructeurs:

std::vector<SHAPECONTOUR>().swap(Contour); 

Et faire la même chose avec d'autres vecteurs de votre code (DrawingPoints,, Points Utilisateurs couleurs).

1

Lorsque vous allouez de gros blocs de mémoire, le CRT en conserve une partie lorsque vous avez besoin d'allouer à nouveau. Vous ne pouvez pas utiliser le Gestionnaire des tâches pour indiquer les fuites.

Si votre classe utilise des membres auto-purgeurs tels que des vecteurs, ils ne fuient pas la mémoire.

+0

Utiliser le Gestionnaire des tâches pour détecter les fuites n'est pas la meilleure idée, mais cela peut sûrement indiquer que votre application fait quelque chose de mal (utilisation élevée du CPU, ne pas revenir au même niveau de mémoire avant le début de l'application, etc.) – virious

+0

@virious: Pour la raison que j'ai soulignée dans le message auquel vous répondez, ce n'est vraiment pas utile, c'est-à-dire que la mémoire change dynamiquement de main. Pour utiliser TM pour prouver que vous avez une fuite de mémoire, vous devez le laisser fonctionner pendant plusieurs jours. – Puppy

+0

Oui, c'est certainement vrai. – virious

0

Quels outils de débogage avez-vous utilisés? Essayez encore deleaker! C'est simple!