ref count the linreg structure so as to avoid double free problems 20120821000505/pspp
authorJohn Darrington <john@darrington.wattle.id.au>
Mon, 20 Aug 2012 19:32:11 +0000 (21:32 +0200)
committerJohn Darrington <john@darrington.wattle.id.au>
Mon, 20 Aug 2012 19:32:11 +0000 (21:32 +0200)
src/language/stats/regression.c
src/math/linreg.c
src/math/linreg.h

index 9e1aba8815e22f173fab6042db2acf5b293e1cef..cb2c3ff31bd2cd77334f38922c3b3b80ad9314c0 100644 (file)
@@ -196,16 +196,15 @@ reg_get_name (const struct dictionary *dict, const char *prefix)
 static bool
 regression_trns_free (void *t_)
 {
-  bool result = true;
   struct reg_trns *t = t_;
 
   if (t->trns_id == t->n_trns)
     {
-      result = linreg_free (t->c);
+      linreg_unref (t->c);
     }
   free (t);
 
-  return result;
+  return true;
 }
 
 static void
@@ -249,6 +248,7 @@ subcommand_save (const struct regression *cmd)
         {
           if ((*lc)->depvar != NULL)
             {
+             (*lc)->refcnt++;
               if (cmd->resid)
                 {
                   reg_save_var (cmd->ds, "RES", regression_trns_resid_proc, *lc,
@@ -401,11 +401,13 @@ cmd_regression (struct lexer *lexer, struct dataset *ds)
   }
 
   if (regression.pred || regression.resid )
-    subcommand_save (&regression);
+    {
+      subcommand_save (&regression);
+    }
  
 
   for (k = 0; k < regression.n_dep_vars; k++)
-    linreg_free (regression.models[k]);
+    linreg_unref (regression.models[k]);
   free (regression.models);
   free (regression.vars);
   free (regression.dep_vars);
@@ -413,7 +415,7 @@ cmd_regression (struct lexer *lexer, struct dataset *ds)
   
  error:
   for (k = 0; k < regression.n_dep_vars; k++)
-    linreg_free (regression.models[k]);
+    linreg_unref (regression.models[k]);
   free (regression.models);
   free (regression.vars);
   free (regression.dep_vars);
@@ -684,7 +686,7 @@ run_regression (const struct regression *cmd, struct casereader *input)
        {
           msg (SE,
               _("No valid data found. This command was skipped."));
-          linreg_free (models[k]);
+          linreg_unref (models[k]);
           models[k] = NULL;
        }
       gsl_matrix_free (this_cm);
index 7c85634a50fd28e558cdb8cfef0d38d30da79838..47d21cf8f5fdfed7f357f96f45038493374b6aab 100644 (file)
@@ -107,14 +107,20 @@ linreg_alloc (const struct variable *depvar, const struct variable **indep_vars,
   c->pred = NULL;
   c->resid = NULL;
 
+  c->refcnt = 1;
   return c;
 }
 
-bool
-linreg_free (void *m)
+void
+linreg_ref (linreg *c)
+{
+  c->refcnt++;
+}
+
+void
+linreg_unref (linreg *c)
 {
-  linreg *c = m;
-  if (c != NULL)
+  if (c && --c->refcnt == 0)
     {
       gsl_vector_free (c->indep_means);
       gsl_vector_free (c->indep_std);
@@ -124,7 +130,6 @@ linreg_free (void *m)
       free (c->coeff);
       free (c);
     }
-  return true;
 }
 
 static void
index 32373f5ed484eceab55fc4b1df8cf019d03860cf..e53a02956e2077e91f58ede8268ed68ab71fd60d 100644 (file)
@@ -90,6 +90,7 @@ typedef struct pspp_linreg_opts_struct pspp_linreg_opts;
 
 struct linreg_struct
 {
+  int refcnt;
   double n_obs;                        /* Number of observations. */
   int n_indeps;                        /* Number of independent variables. */
   int n_coeffs;                 /* The intercept is not considered a
@@ -153,7 +154,8 @@ typedef struct linreg_struct linreg;
 linreg *linreg_alloc (const struct variable *, const struct variable **, 
                      double, size_t);
 
-bool linreg_free (void *);
+void linreg_unref (linreg *);
+void linreg_ref (linreg *c);
 
 /*
   Fit the linear model via least squares. All pointers passed to pspp_linreg