[gegl] operations: Fix memory leaks in seamless clone



commit dd3660fd44185464765a9af174a0302a25dc5372
Author: awaw fumin <awawfumin gmail com>
Date:   Fri Feb 21 11:45:24 2014 +0800

    operations: Fix memory leaks in seamless clone
    
    The leaks detected and fixed herein were discovered using the
    "Leaks" template in Apple's "Instruments" tool.
    At least according to Instruments, there are completely no leaks anymore
    after applying the fixes in this commit.

 libs/poly2tri-c/poly2tri-c/refine/cdt.c            |    2 ++
 libs/poly2tri-c/poly2tri-c/refine/cluster.c        |   11 +++++++++--
 .../poly2tri-c/refine/delaunay-terminator.c        |    5 +++++
 libs/poly2tri-c/poly2tri-c/refine/mesh.c           |   10 ++++++----
 seamless-clone/sc-context.c                        |    8 ++++++++
 seamless-clone/sc-sample.c                         |    3 +++
 6 files changed, 33 insertions(+), 6 deletions(-)
---
diff --git a/libs/poly2tri-c/poly2tri-c/refine/cdt.c b/libs/poly2tri-c/poly2tri-c/refine/cdt.c
index 7dc1d11..4929d34 100644
--- a/libs/poly2tri-c/poly2tri-c/refine/cdt.c
+++ b/libs/poly2tri-c/poly2tri-c/refine/cdt.c
@@ -319,6 +319,8 @@ p2tr_cdt_insert_point (P2trCDT           *self,
           GList *parts = p2tr_cdt_split_edge (self, edge, pt), *eIter;
           for (eIter = parts; eIter != NULL; eIter = eIter->next)
             p2tr_edge_unref ((P2trEdge*)eIter->data);
+          g_list_free(parts);
+
           inserted = TRUE;
           break;
         }
diff --git a/libs/poly2tri-c/poly2tri-c/refine/cluster.c b/libs/poly2tri-c/poly2tri-c/refine/cluster.c
index 3e6ce25..ba04435 100644
--- a/libs/poly2tri-c/poly2tri-c/refine/cluster.c
+++ b/libs/poly2tri-c/poly2tri-c/refine/cluster.c
@@ -81,7 +81,7 @@ p2tr_cluster_get_for (P2trPoint   *P,
 
   g_queue_push_head (&cluster->edges, p2tr_edge_ref (E));
 
-  current = E;
+  current = p2tr_edge_ref (E);
   next = p2tr_point_edge_cw (P, current);
   
   while (next != g_queue_peek_head (&cluster->edges)
@@ -89,22 +89,29 @@ p2tr_cluster_get_for (P2trPoint   *P,
       && p2tr_cluster_cw_tri_between_is_in_domain (current, next))
     {
       g_queue_push_tail (&cluster->edges, p2tr_edge_ref (next));
+      p2tr_edge_unref (current);
       current = next;
       next = p2tr_point_edge_cw (P, current);
       cluster->min_angle = MIN (cluster->min_angle, temp_angle);
     }
+  p2tr_edge_unref (current);
+  p2tr_edge_unref (next);
 
-  current = E;
+  current = p2tr_edge_ref (E);
   next = p2tr_point_edge_ccw(P, current);
+  p2tr_edge_unref(next);
   while (next != g_queue_peek_tail (&cluster->edges)
       && (temp_angle = p2tr_edge_angle_between (current->mirror, next)) <= P2TR_CLUSTER_LIMIT_ANGLE
       && p2tr_cluster_cw_tri_between_is_in_domain (next, current))
     {
       g_queue_push_head (&cluster->edges, p2tr_edge_ref (next));
+      p2tr_edge_unref (current);
       current = next;
       next = p2tr_point_edge_ccw (P, current);
       cluster->min_angle = MIN(cluster->min_angle, temp_angle);
     }
+  p2tr_edge_unref (current);
+  p2tr_edge_unref (next);
 
   return cluster;
 }
diff --git a/libs/poly2tri-c/poly2tri-c/refine/delaunay-terminator.c 
b/libs/poly2tri-c/poly2tri-c/refine/delaunay-terminator.c
index 48ff030..1de1fea 100644
--- a/libs/poly2tri-c/poly2tri-c/refine/delaunay-terminator.c
+++ b/libs/poly2tri-c/poly2tri-c/refine/delaunay-terminator.c
@@ -105,6 +105,8 @@ p2tr_cdt_get_segments_encroached_by (P2trCDT   *self,
        * since it's still faster */
       if (e->constrained && p2tr_cdt_is_encroached (e))
         p2tr_vedge_set_add2 (encroached, p2tr_vedge_new2 (e));
+
+      p2tr_edge_unref(e);
     }
 
   return encroached;
@@ -431,6 +433,9 @@ SplitEncroachedSubsegments (P2trDelaunayTerminator *self, gdouble theta, P2trTri
               p2tr_dt_enqueue_segment (self, e);
             p2tr_edge_unref (e);
           }
+
+        g_list_free(parts);
+        p2tr_point_unref(Pv);
       }
     p2tr_edge_unref (s);
   }
diff --git a/libs/poly2tri-c/poly2tri-c/refine/mesh.c b/libs/poly2tri-c/poly2tri-c/refine/mesh.c
index 4478178..0b5ca50 100644
--- a/libs/poly2tri-c/poly2tri-c/refine/mesh.c
+++ b/libs/poly2tri-c/poly2tri-c/refine/mesh.c
@@ -200,11 +200,11 @@ p2tr_mesh_action_group_commit (P2trMesh *self)
 
   g_assert (self->record_undo);
 
+  self->record_undo = FALSE;
+
   for (iter = self->undo.head; iter != NULL; iter = iter->next)
     p2tr_mesh_action_unref ((P2trMeshAction*)iter->data);
   g_queue_clear (&self->undo);
-
-  self->record_undo = FALSE;
 }
 
 void
@@ -214,14 +214,16 @@ p2tr_mesh_action_group_undo (P2trMesh *self)
 
   g_assert (self->record_undo);
 
+  /* Set the record_undo flag to FALSE before p2tr_mesh_action_undo, so that
+   * we don't create zombie objects therein. */
+  self->record_undo = FALSE;
+
   for (iter = self->undo.tail; iter != NULL; iter = iter->prev)
     {
       p2tr_mesh_action_undo ((P2trMeshAction*)iter->data, self);
       p2tr_mesh_action_unref ((P2trMeshAction*)iter->data);
     }
   g_queue_clear (&self->undo);
-
-  self->record_undo = FALSE;
 }
 
 void
diff --git a/seamless-clone/sc-context.c b/seamless-clone/sc-context.c
index b41ba1c..9b814d7 100644
--- a/seamless-clone/sc-context.c
+++ b/seamless-clone/sc-context.c
@@ -772,7 +772,15 @@ gegl_sc_context_free (GeglScContext *context)
     g_object_unref (context->uvt);
 
   gegl_sc_mesh_sampling_free (context->sampling);
+
+  /* p2tr_mesh_clear is necessary since p2tr_mesh_unref itself is unable to
+   * free context->mesh entirely.
+   * The reason is because the N points in context->mesh holds N references
+   * back to context->mesh itself, and an initiative to break these circular
+   * references is needed. */
+  p2tr_mesh_clear(context->mesh);
   p2tr_mesh_unref (context->mesh);
+
   gegl_sc_outline_free (context->outline);
 
   g_slice_free (GeglScContext, context);
diff --git a/seamless-clone/sc-sample.c b/seamless-clone/sc-sample.c
index b6e7338..8f5c7fd 100644
--- a/seamless-clone/sc-sample.c
+++ b/seamless-clone/sc-sample.c
@@ -152,6 +152,9 @@ gegl_sc_compute_sample_list_weights (gdouble           Px,
       sl->total_weight += weightTemp;
       g_array_append_val (sl->weights, weightTemp);
     }
+
+  g_free (norms);
+  g_free (tan_as_half);
 }
 
 GeglScSampleList*


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]