From b9d026337badca5f46ee1d1649e3dd9c778b2556 Mon Sep 17 00:00:00 2001 From: John Darrington Date: Mon, 20 Aug 2012 21:32:11 +0200 Subject: [PATCH] ref count the linreg structure so as to avoid double free problems --- src/language/stats/regression.c | 16 +++++++++------- src/math/linreg.c | 15 ++++++++++----- src/math/linreg.h | 4 +++- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/language/stats/regression.c b/src/language/stats/regression.c index 9e1aba8815..cb2c3ff31b 100644 --- a/src/language/stats/regression.c +++ b/src/language/stats/regression.c @@ -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 (®ression); + { + subcommand_save (®ression); + } 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); diff --git a/src/math/linreg.c b/src/math/linreg.c index 7c85634a50..47d21cf8f5 100644 --- a/src/math/linreg.c +++ b/src/math/linreg.c @@ -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 diff --git a/src/math/linreg.h b/src/math/linreg.h index 32373f5ed4..e53a02956e 100644 --- a/src/math/linreg.h +++ b/src/math/linreg.h @@ -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 -- 2.30.2