views:

121

answers:

5

I have a class here that is defined like this:

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);
};

Here is what I did as a test. I created a global std::vector<OGLSHAPE> test .

In the function I was using, I created

OGLSHAPE t.

I then pushed 50,000 copies of t into test.

I then instantly cleared test and used the swap trick to really deallocate it.

I noticed that all the memory was properly freed as I would expect.

I then did the same thing but before pushing t into test, I pushed a SHAPECONTOUR (which I had just created without modifying or adding anything into the contour) before pushing t into test.

This time after clearing test, 3 more megabytes had been allocated. I did it again allocating twice as many and now 6MB we remaining. The memory usage of the program peaked at 150MB and it went down to 12MB, but it should be at 8.5MB. Therefore, this must be classified as a memory leak, although I do not see how. There is nothing that I see that could do that. SHAPECONTOUR is merely a structure of vectors with a nested structure of vectors.

Why would this cause a leak, and how could I fix it?

Thanks

+1  A: 

If you've deleted everything, there is no leak, by definition. I don't see any unwrapped pointers, ergo everything gets deleted. Therefore, you have no leaks.

Likely, the OS has simply decided to leave that memory available to your program, for whatever reason. (It hasn't "reclaimed" it.) Or maybe it needs to allocate in groups of4MB, and so going from 12MB to 8MB wouldn't leave enough required memory. Or...

You're cutting out other reasons entirely; you should use a real memory leak tool to find memory leaks.

GMan
+1 to OS not reclaiming memory. `new` allocates memory from a separate pool that is managed by the runtime library and `delete` doesn't always return the freed memory immediately to the OS.
casablanca
Is jt normal that it never reclaims it?
Milo
@user: Yes. It's much simpler to leave that memory for your program, because further allocations don't require the OS actually get a new page of memory for you. If another program needs memory and the OS is low, then it'll take it from you.
GMan
Remember it's a virtual memory machine. The fact your program has memory allocated doesn't necessarily mean that RAM memory is being used.
Brian Hooper
A: 

I would suggest to use a leak detection tool to find out if you really have a leak. For example for Windows dev you can use Visual Leak Detetor (VLD).

If you do indeed have a leak then it is probably not where you think it is.

Also you may just be wrong in that there is no leak at all. For example if you are looking just at the stats via something like task manager, this does not mean there is a leak in your program. The OS that runs your program is a separate beast than the programming language that you may have a leak inside of. I.e. the OS can take longer to reclaim freed memory.

Edit:

If you want to make sure the vector has capacity 0 it is pretty common to do the following:

v.swap(std::vector<char>());
assert(v.capacity() == 0);
Brian R. Bondy
Visual Leak Detector detected no leaks.
Milo
Then you probably have no leaks. Try to insert a leak on purpose (use new without delete) and then see if it detects it to ensure you're using it correctly.
Brian R. Bondy
It detected the new thing, I think its not a leak and rather the fact that std::vector only frees on ~vector. But I still cant find the culprit responsible....
Milo
A: 

How about explicitly clearing the vectors of SHAPECONTOUR in the destructor of OGLSHAPE? Rerun your test with this & check if you still have the observed leak.

Raam
A: 

How are you clearing that vectors? Try using in destructors something like this:

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

And do the same with other vectors from your code(UserPoints, DrawingPoints, colors).

virious
A: 

When you allocate large chunks of memory, the CRT keeps some of it around for when you need to allocate again. You can't use Task Manager to indicate leaks.

If your class uses self-clearing members like vector, they do not leak memory.

DeadMG
Using the Task Manager for leak detection is not the best idea but it surely can indicate that your application is doing something wrong (high CPU usage, not coming back on the same memory level from before application start, etc.)
virious
@virious: For the reason that I outlined in the post that you're responding to, it's actually not of any use, which is that memory changes hands dynamically an awful, awful lot. In order to use TM to prove that you have a memory leak, you'd have to leave it running for days.
DeadMG
@DeadMG: Yes, that's certainly true.
virious