From 16179f34cd38eca4eee6866bd2d26c7d7b347161 Mon Sep 17 00:00:00 2001 From: Daniel Richard G Date: Thu, 19 Sep 2013 00:33:12 -0400 Subject: [PATCH] Enabled freeing of (most) allocated memory on program exit The Valgrind tool can give a full accounting of what memory allocations have yet to be free()d when the program exits. It is easier to find actual memory leaks in the code if all non-leaked allocations are elided from that accounting, which is most easily accomplished by free()ing them. The "most" qualifier is there because some allocations are difficult/ impossible to free, as they are internal to libraries like OpenGL and Xft. The best we can hope for is to cover all allocations made by SolveSpace directly. --- dsc.h | 3 +++ groupmesh.cpp | 3 ++- sketch.h | 14 ++++++++++++++ solvespace.cpp | 17 +++++++++++++++++ solvespace.h | 14 ++++++++++++++ system.cpp | 6 ++++++ win32/w32main.cpp | 5 +++++ 7 files changed, 61 insertions(+), 1 deletion(-) diff --git a/dsc.h b/dsc.h index b2a4faa..cbccb7e 100644 --- a/dsc.h +++ b/dsc.h @@ -362,6 +362,9 @@ public: } void Clear(void) { + for(int i = 0; i < n; i++) { + elem[i].Clear(); + } elemsAllocated = n = 0; if(elem) MemFree(elem); elem = NULL; diff --git a/groupmesh.cpp b/groupmesh.cpp index 444ac13..24199bc 100644 --- a/groupmesh.cpp +++ b/groupmesh.cpp @@ -38,7 +38,7 @@ void Group::AssembleLoops(bool *allClosed, // This is a zero-length edge. *allNonZeroLen = false; polyError.errorPointAt = sb->ctrl[0]; - return; + goto done; } } @@ -50,6 +50,7 @@ void Group::AssembleLoops(bool *allClosed, allClosed, &(polyError.notClosedAt), allCoplanar, &(polyError.errorPointAt), &bezierOpens); + done: sbl.Clear(); } diff --git a/sketch.h b/sketch.h index a0ef5e1..d6dd3ed 100644 --- a/sketch.h +++ b/sketch.h @@ -80,6 +80,8 @@ public: hEntity input; int copyNumber; // (input, copyNumber) gets mapped to ((Request)xxx).entity(h.v) + + void Clear(void) {} }; // A set of requests. Every request must have an associated group. @@ -289,6 +291,8 @@ public: void Generate(EntityList *entity, ParamList *param); char *DescriptionString(void); + + void Clear(void) {} }; #define MAX_POINTS_IN_ENTITY (12) @@ -428,6 +432,8 @@ public: void AddEq(IdList *l, Expr *expr, int index); void GenerateEquations(IdList *l); + + void Clear(void) {} }; class Entity : public EntityBase { @@ -514,6 +520,8 @@ public: hParam substd; static const hParam NO_PARAM; + + void Clear(void) {} }; @@ -601,6 +609,8 @@ public: static Expr *PointPlaneDistance(ExprVector p, hEntity plane); static Expr *VectorsParallel(int eq, ExprVector a, ExprVector b); static ExprVector PointInThreeSpace(hEntity workplane, Expr *u, Expr *v); + + void Clear(void) {} }; class Constraint : public ConstraintBase { @@ -668,6 +678,8 @@ public: hEquation h; Expr *e; + + void Clear(void) {} }; @@ -759,6 +771,8 @@ public: static hStyle ForEntity(hEntity he); char *DescriptionString(void); + + void Clear(void) {} }; diff --git a/solvespace.cpp b/solvespace.cpp index bf644ed..40da6cd 100644 --- a/solvespace.cpp +++ b/solvespace.cpp @@ -734,3 +734,20 @@ void SolveSpace::MenuHelp(int id) { default: oops(); } } + +void SolveSpace::Clear(void) { + sys.Clear(); + for(int i = 0; i < MAX_UNDO; i++) { + if(i < undo.cnt) undo.d[i].Clear(); + if(i < redo.cnt) redo.d[i].Clear(); + } +} + +void Sketch::Clear(void) { + group.Clear(); + constraint.Clear(); + request.Clear(); + style.Clear(); + entity.Clear(); + param.Clear(); +} diff --git a/solvespace.h b/solvespace.h index ba0d856..a5437fe 100644 --- a/solvespace.h +++ b/solvespace.h @@ -328,6 +328,8 @@ public: }; int Solve(Group *g, int *dof, List *bad, bool andFindBad, bool andFindFree); + + void Clear(void); }; class TtfFont { @@ -577,6 +579,8 @@ public: inline Request *GetRequest(hRequest h) { return request.FindById(h); } inline Group *GetGroup (hGroup h) { return group. FindById(h); } // Styles are handled a bit differently. + + void Clear(void); }; #undef ENTITY #undef CONSTRAINT @@ -594,6 +598,14 @@ public: IdList param; IdList style; hGroup activeGroup; + + void Clear(void) { + group.Clear(); + request.Clear(); + constraint.Clear(); + param.Clear(); + style.Clear(); + } } UndoState; enum { MAX_UNDO = 16 }; typedef struct { @@ -813,6 +825,8 @@ public: void DoLater(void); static void MenuHelp(int id); + + void Clear(void); }; extern SolveSpace SS; diff --git a/system.cpp b/system.cpp index 6d63fb5..fe58a0f 100644 --- a/system.cpp +++ b/system.cpp @@ -526,3 +526,9 @@ didnt_converge: return System::DIDNT_CONVERGE; } +void System::Clear(void) { + entity.Clear(); + param.Clear(); + eq.Clear(); + dragged.Clear(); +} diff --git a/win32/w32main.cpp b/win32/w32main.cpp index 1846761..471b120 100644 --- a/win32/w32main.cpp +++ b/win32/w32main.cpp @@ -1206,5 +1206,10 @@ done: // Write everything back to the registry FreezeWindowPos(TextWnd); FreezeWindowPos(GraphicsWnd); + + // Free the memory we've used; anything that remains is a leak. + SK.Clear(); + SS.Clear(); + return 0; }