r20042 - gnucash/trunk/src/engine - Fix more memory leaks. Also, when closing a book (to open a new one, not year end), free objects.

Phil Longstaff plongstaff at code.gnucash.org
Sun Jan 9 13:01:47 EST 2011


Author: plongstaff
Date: 2011-01-09 13:01:47 -0500 (Sun, 09 Jan 2011)
New Revision: 20042
Trac: http://svn.gnucash.org/trac/changeset/20042

Modified:
   gnucash/trunk/src/engine/Account.c
   gnucash/trunk/src/engine/Recurrence.c
   gnucash/trunk/src/engine/Recurrence.h
   gnucash/trunk/src/engine/SX-book.c
   gnucash/trunk/src/engine/SchedXaction.c
   gnucash/trunk/src/engine/Transaction.c
   gnucash/trunk/src/engine/engine.i
   gnucash/trunk/src/engine/gnc-lot.c
Log:
Fix more memory leaks.  Also, when closing a book (to open a new one, not year end), free objects.


Modified: gnucash/trunk/src/engine/Account.c
===================================================================
--- gnucash/trunk/src/engine/Account.c	2011-01-09 18:00:32 UTC (rev 20041)
+++ gnucash/trunk/src/engine/Account.c	2011-01-09 18:01:47 UTC (rev 20042)
@@ -266,6 +266,10 @@
         else
             g_free ( acct_name );
     }
+    if (accounts != NULL)
+    {
+        g_list_free(accounts);
+    }
 
     return invalid_list;
 }
@@ -1230,13 +1234,26 @@
         PINFO ("freeing splits for account %p (%s)",
                acc, priv->accountName ? priv->accountName : "(null)");
 
-        slist = g_list_copy(priv->splits);
-        for (lp = slist; lp; lp = lp->next)
+        book = qof_instance_get_book(acc);
+
+        /* If book is shutting down, just clear the split list.  The splits
+           themselves will be destroyed by the transaction code */
+        if (!qof_book_shutting_down(book))
         {
-            Split *s = lp->data;
-            xaccSplitDestroy (s);
+            slist = g_list_copy(priv->splits);
+            for (lp = slist; lp; lp = lp->next)
+            {
+                Split *s = lp->data;
+                xaccSplitDestroy (s);
+            }
+            g_list_free(slist);
         }
-        g_list_free(slist);
+        else
+        {
+            g_list_free(priv->splits);
+            priv->splits = NULL;
+        }
+
         /* It turns out there's a case where this assertion does not hold:
            When the user tries to delete an Imbalance account, while also
            deleting all the splits in it.  The splits will just get
@@ -1245,18 +1262,17 @@
            g_assert(priv->splits == NULL || qof_book_shutting_down(acc->inst.book));
         */
 
-        book = qof_instance_get_book(acc);
         if (!qof_book_shutting_down(book))
         {
             col = qof_book_get_collection(book, GNC_ID_TRANS);
             qof_collection_foreach(col, destroy_pending_splits_for_account, acc);
-        }
 
-        /* the lots should be empty by now */
-        for (lp = priv->lots; lp; lp = lp->next)
-        {
-            GNCLot *lot = lp->data;
-            gnc_lot_destroy (lot);
+            /* the lots should be empty by now */
+            for (lp = priv->lots; lp; lp = lp->next)
+            {
+                GNCLot *lot = lp->data;
+                gnc_lot_destroy (lot);
+            }
         }
         g_list_free(priv->lots);
         priv->lots = NULL;
@@ -4807,6 +4823,16 @@
 
 /* ================================================================ */
 /* QofObject function implementation and registration */
+
+static void
+gnc_account_book_end(QofBook* book)
+{
+    Account *root_account = gnc_book_get_root_account(book);
+
+    xaccAccountBeginEdit(root_account);
+    xaccAccountDestroy(root_account);
+}
+
 #ifdef _MSC_VER
 /* MSVC compiler doesn't have C99 "designated initializers"
  * so we wrap them in a macro that is empty on MSVC. */
@@ -4821,7 +4847,7 @@
     DI(.type_label        = ) "Account",
     DI(.create            = ) (gpointer)xaccMallocAccount,
     DI(.book_begin        = ) NULL,
-    DI(.book_end          = ) NULL,
+    DI(.book_end          = ) gnc_account_book_end,
     DI(.is_dirty          = ) qof_collection_is_dirty,
     DI(.mark_clean        = ) qof_collection_mark_clean,
     DI(.foreach           = ) qof_collection_foreach,

Modified: gnucash/trunk/src/engine/Recurrence.c
===================================================================
--- gnucash/trunk/src/engine/Recurrence.c	2011-01-09 18:00:32 UTC (rev 20041)
+++ gnucash/trunk/src/engine/Recurrence.c	2011-01-09 18:01:47 UTC (rev 20042)
@@ -541,9 +541,9 @@
 }
 
 gboolean
-recurrenceListIsWeeklyMultiple(GList *recurrences)
+recurrenceListIsWeeklyMultiple(const GList *recurrences)
 {
-    GList *r_iter;
+    const GList *r_iter;
 
     for (r_iter = recurrences; r_iter != NULL; r_iter = r_iter->next)
     {

Modified: gnucash/trunk/src/engine/Recurrence.h
===================================================================
--- gnucash/trunk/src/engine/Recurrence.h	2011-01-09 18:00:32 UTC (rev 20041)
+++ gnucash/trunk/src/engine/Recurrence.h	2011-01-09 18:01:47 UTC (rev 20042)
@@ -161,7 +161,7 @@
 /** @return True if the recurrence list is a common "semi-monthly" recurrence. **/
 gboolean recurrenceListIsSemiMonthly(GList *recurrences);
 /** @return True if the recurrence list is a common "weekly" recurrence. **/
-gboolean recurrenceListIsWeeklyMultiple(GList *recurrences);
+gboolean recurrenceListIsWeeklyMultiple(const GList *recurrences);
 
 /**
  * Pretty-print an intentionally-short summary of the period of a (GList of)

Modified: gnucash/trunk/src/engine/SX-book.c
===================================================================
--- gnucash/trunk/src/engine/SX-book.c	2011-01-09 18:00:32 UTC (rev 20041)
+++ gnucash/trunk/src/engine/SX-book.c	2011-01-09 18:01:47 UTC (rev 20042)
@@ -125,7 +125,7 @@
 static void
 sxtg_book_end (QofBook *book)
 {
-    gnc_book_set_template_root (book, NULL);
+//    gnc_book_set_template_root (book, NULL);
 }
 
 static gboolean

Modified: gnucash/trunk/src/engine/SchedXaction.c
===================================================================
--- gnucash/trunk/src/engine/SchedXaction.c	2011-01-09 18:00:32 UTC (rev 20041)
+++ gnucash/trunk/src/engine/SchedXaction.c	2011-01-09 18:01:47 UTC (rev 20042)
@@ -483,11 +483,15 @@
 
     /*
      * xaccAccountDestroy removes the account from
-     * its group for us AFAICT
+     * its group for us AFAICT.  If shutting down,
+     * the account is being deleted separately.
      */
 
-    xaccAccountBeginEdit(sx->template_acct);
-    xaccAccountDestroy(sx->template_acct);
+    if (!qof_book_shutting_down(qof_instance_get_book(sx)))
+    {
+        xaccAccountBeginEdit(sx->template_acct);
+        xaccAccountDestroy(sx->template_acct);
+    }
 
     for ( l = sx->deferredList; l; l = l->next )
     {
@@ -1248,6 +1252,9 @@
  * temporal-state-data instance list.  The list should not be modified by the
  * caller; use the gnc_sx_{add,remove}_defer_instance() functions to modifiy
  * the list.
+ *
+ * @param sx Scheduled transaction
+ * @return Defer list which must not be modified by the caller
  **/
 GList*
 gnc_sx_get_defer_instances( SchedXaction *sx )
@@ -1255,6 +1262,29 @@
     return sx->deferredList;
 }
 
+static void
+destroy_sx_on_book_close(QofInstance *ent, gpointer data)
+{
+    SchedXaction* sx = GNC_SCHEDXACTION(ent);
+
+    gnc_sx_begin_edit(sx);
+    xaccSchedXactionDestroy(sx);
+}
+
+/**
+ * Destroys all SXes in the book because the book is being destroyed.
+ *
+ * @param book Book being destroyed
+ */
+static void
+gnc_sx_book_end(QofBook* book)
+{
+    QofCollection *col;
+
+    col = qof_book_get_collection(book, GNC_ID_SCHEDXACTION);
+    qof_collection_foreach(col, destroy_sx_on_book_close, NULL);
+}
+
 #ifdef _MSC_VER
 /* MSVC compiler doesn't have C99 "designated initializers"
  * so we wrap them in a macro that is empty on MSVC. */
@@ -1269,7 +1299,7 @@
     DI(.type_label        = ) "Scheduled Transaction",
     DI(.create            = ) (gpointer)xaccSchedXactionMalloc,
     DI(.book_begin        = ) NULL,
-    DI(.book_end          = ) NULL,
+    DI(.book_end          = ) gnc_sx_book_end,
     DI(.is_dirty          = ) qof_collection_is_dirty,
     DI(.mark_clean        = ) qof_collection_mark_clean,
     DI(.foreach           = ) qof_collection_foreach,

Modified: gnucash/trunk/src/engine/Transaction.c
===================================================================
--- gnucash/trunk/src/engine/Transaction.c	2011-01-09 18:00:32 UTC (rev 20041)
+++ gnucash/trunk/src/engine/Transaction.c	2011-01-09 18:01:47 UTC (rev 20042)
@@ -1182,14 +1182,26 @@
 
     qof_event_gen (&trans->inst, QOF_EVENT_DESTROY, NULL);
 
-    /* We only own the splits that still think they belong to us. */
-    trans->splits = g_list_copy(trans->splits);
+    /* We only own the splits that still think they belong to us.   This is done
+       in 2 steps.  In the first, the splits are marked as being destroyed, but they
+       are not destroyed yet.  In the second, the destruction is committed which will
+       do the actual destruction.  If both steps are done for a split before they are
+       done for the next split, then a split will still be on the split list after it
+       has been freed.  This can cause other parts of the code (e.g. in xaccSplitDestroy())
+       to reference the split after it has been freed. */
     for (node = trans->splits; node; node = node->next)
     {
         Split *s = node->data;
         if (s->parent == trans)
         {
             xaccSplitDestroy(s);
+        }
+    }
+    for (node = trans->splits; node; node = node->next)
+    {
+        Split *s = node->data;
+        if (s->parent == trans)
+        {
             xaccSplitCommitEdit(s);
         }
     }
@@ -2296,6 +2308,27 @@
 \********************************************************************/
 /* QofObject function implementation */
 
+static void
+destroy_tx_on_book_close(QofInstance *ent, gpointer data)
+{
+    Transaction* tx = GNC_TRANSACTION(ent);
+
+    xaccTransDestroy(tx);
+}
+
+/** Handles book end - frees all transactions from the book
+ *
+ * @param book Book being closed
+ */
+static void
+gnc_transaction_book_end(QofBook* book)
+{
+    QofCollection *col;
+
+    col = qof_book_get_collection(book, GNC_ID_TRANS);
+    qof_collection_foreach(col, destroy_tx_on_book_close, NULL);
+}
+
 #ifdef _MSC_VER
 /* MSVC compiler doesn't have C99 "designated initializers"
  * so we wrap them in a macro that is empty on MSVC. */
@@ -2312,7 +2345,7 @@
     DI(.type_label        = ) "Transaction",
     DI(.create            = ) (gpointer)xaccMallocTransaction,
     DI(.book_begin        = ) NULL,
-    DI(.book_end          = ) NULL,
+    DI(.book_end          = ) gnc_transaction_book_end,
     DI(.is_dirty          = ) qof_collection_is_dirty,
     DI(.mark_clean        = ) qof_collection_mark_clean,
     DI(.foreach           = ) qof_collection_foreach,

Modified: gnucash/trunk/src/engine/engine.i
===================================================================
--- gnucash/trunk/src/engine/engine.i	2011-01-09 18:00:32 UTC (rev 20041)
+++ gnucash/trunk/src/engine/engine.i	2011-01-09 18:01:47 UTC (rev 20042)
@@ -134,11 +134,14 @@
   {
     SCM key_scm = SCM_CAR (path_scm);
     char *key;
+    gchar* gkey;
 
     if (!scm_is_string (key_scm))
       break;
 
-    key = g_strdup (scm_to_locale_string (key_scm));
+    key = scm_to_locale_string (key_scm);
+    gkey = g_strdup (key);
+    gnc_free_scm_locale_string(key);
 
     path = g_list_prepend (path, key);
 

Modified: gnucash/trunk/src/engine/gnc-lot.c
===================================================================
--- gnucash/trunk/src/engine/gnc-lot.c	2011-01-09 18:00:32 UTC (rev 20041)
+++ gnucash/trunk/src/engine/gnc-lot.c	2011-01-09 18:01:47 UTC (rev 20042)
@@ -614,6 +614,23 @@
 
 /* ============================================================= */
 
+static void
+destroy_lot_on_book_close(QofInstance *ent, gpointer data)
+{
+    GNCLot* lot = GNC_LOT(ent);
+
+    gnc_lot_destroy(lot);
+}
+
+static void
+gnc_lot_book_end(QofBook* book)
+{
+    QofCollection *col;
+
+    col = qof_book_get_collection(book, GNC_ID_LOT);
+    qof_collection_foreach(col, destroy_lot_on_book_close, NULL);
+}
+
 #ifdef _MSC_VER
 /* MSVC compiler doesn't have C99 "designated initializers"
  * so we wrap them in a macro that is empty on MSVC. */
@@ -628,7 +645,7 @@
     DI(.type_label        = ) "Lot",
     DI(.create            = ) (gpointer)gnc_lot_new,
     DI(.book_begin        = ) NULL,
-    DI(.book_end          = ) NULL,
+    DI(.book_end          = ) gnc_lot_book_end,
     DI(.is_dirty          = ) qof_collection_is_dirty,
     DI(.mark_clean        = ) qof_collection_mark_clean,
     DI(.foreach           = ) qof_collection_foreach,



More information about the gnucash-changes mailing list