Valgrind says "stack allocation," I say "heap allocation"

Posted by Joel J. Adamson on Stack Overflow See other posts from Stack Overflow or by Joel J. Adamson
Published on 2010-04-21T14:28:08Z Indexed on 2010/04/22 14:23 UTC
Read the original article Hit count: 325

Filed under:
|
|
|

Dear Friends,

I am trying to trace a segfault with valgrind. I get the following message from valgrind:

==3683== Conditional jump or move depends on uninitialised value(s)
==3683==    at 0x4C277C5: sparse_mat_mat_kron (sparse.c:165)
==3683==    by 0x4C2706E: rec_mating (rec.c:176)
==3683==    by 0x401C1C: age_dep_iterate (age_dep.c:287)
==3683==    by 0x4014CB: main (age_dep.c:92)
==3683==  Uninitialised value was created by a stack allocation
==3683==    at 0x401848: age_dep_init_params (age_dep.c:131)
==3683== 
==3683== Conditional jump or move depends on uninitialised value(s)
==3683==    at 0x4C277C7: sparse_mat_mat_kron (sparse.c:165)
==3683==    by 0x4C2706E: rec_mating (rec.c:176)
==3683==    by 0x401C1C: age_dep_iterate (age_dep.c:287)
==3683==    by 0x4014CB: main (age_dep.c:92)
==3683==  Uninitialised value was created by a stack allocation
==3683==    at 0x401848: age_dep_init_params (age_dep.c:131)

However, here's the offending line:

 /* allocate mating table */
  age_dep_data->mtable = malloc (age_dep_data->geno * sizeof (double *));
  if (age_dep_data->mtable == NULL)
    error (ENOMEM, ENOMEM, nullmsg, __LINE__);
  for (int j = 0; j < age_dep_data->geno; j++)
    {      
 131=>     age_dep_data->mtable[j] = calloc (age_dep_data->geno, sizeof (double));
      if (age_dep_data->mtable[j] == NULL)
 error (ENOMEM, ENOMEM, nullmsg, __LINE__);
    }

What gives? I thought any call to malloc or calloc allocated heap space; there is no other variable allocated here, right? Is it possible there's another allocation going on (the offending stack allocation) that I'm not seeing?

You asked to see the code, here goes: /*

  Copyright 2010 Joel J. Adamson <[email protected]>

  $Id: age_dep.c 1010 2010-04-21 19:19:16Z joel $

  age_dep.c:main file

  Joel J. Adamson   -- http://www.unc.edu/~adamsonj
  Servedio Lab
  University of North Carolina at Chapel Hill
  CB #3280, Coker Hall
  Chapel Hill, NC 27599-3280

  This file is part of an investigation of age-dependent sexual
  selection.  

  This code is free software: you can redistribute it and/or modify it
  under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This software is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with haploid.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "age_dep.h"

/* global variables */
extern struct argp age_dep_argp;
/* global error message variables */
char * nullmsg = "Null pointer: %i";

/* error message for conversions: */
char * errmsg = "Representation error: %s";

/* precision for formatted output: */
const char prec[] = "%-#9.8f ";

const size_t age_max = AGEMAX; /* maximum age of males */

static int keep_going_p = 1;

int
main (int argc, char ** argv)
{
  /* often used counters: */
  int i, j;
  /* read the command line */
  struct age_dep_args age_dep_args = { NULL, NULL, NULL };
  argp_parse (&age_dep_argp, argc, argv, 0, 0, &age_dep_args);
  /* set the parameters here: */
  /* initialize an age_dep_params structure, set the members */
  age_dep_params_t * params = malloc (sizeof (age_dep_params_t));
  if (params == NULL)
    error (ENOMEM, ENOMEM, nullmsg, __LINE__);
  age_dep_init_params (params, &age_dep_args);
  /* initialize frequencies: this initializes a list of pointers to
     initial frqeuencies, terminated by a NULL pointer*/
  params->freqs = age_dep_init (&age_dep_args);
  params->by = 0.0;
  /* what range of parameters do we want, and with what stepsize? */
  /* we should go from 0 to half-of-theta with a step size of about
     0.01 */
  double    from     = 0.0;
  double    to   = params->theta / 2.0;
  double    stepsz   = 0.01; /* did you think I would spell the
                    whole word? */
  unsigned int  numparts = floor(to / stepsz);

  do
    {
#pragma omp parallel for private(i) firstprivate(params) \
  shared(stepsz, numparts)
      for (i = 0; i < numparts; i++)
    {
      params->by = i * stepsz;
      int tries = 0;
      while (keep_going_p)
        {
          /* each time through, modify mfreqs and mating table, then go
         again */
          keep_going_p = age_dep_iterate (params, ++tries);
          if (keep_going_p == ERANGE)
        error (ERANGE, ERANGE, "Failure to converge\n");
        }
      fprintf (stdout, "%i iterations\n", tries);
    } /* for i < numparts */
      params->freqs = params->freqs->next;
    } while (params->freqs->next != NULL);
  return 0;
}


inline double
age_dep_pmate (double age_dep_t, unsigned int genot, double bp, double ba)
{
  /* the probability of mating between these phenotypes */
  /* the female preference depends on whether the female has the
     preference allele, the strength of preference (parameter bp) and
     the male phenotype (age_dep_t); if the female lacks the
     preference allele, then this will return 0, which is not quite
     accurate; it should return 1 */

  return  bits_isset (genot, CLOCI)?
    1.0 - exp (-bp * age_dep_t) + ba:
    1.0;
}

inline double
age_dep_trait (int age, unsigned int genot, double by)
{
  /* return the male trait, a function of the trait locus, age, the
     age-dependent scaling parameter (bx) and the males condition
     genotype */
  double C;
  double T;

  /* get the male's condition genotype */
  C = (double) bits_popcount (bits_extract (0, CLOCI, genot));

  /* get his trait genotype */
  T = bits_isset (genot, CLOCI + 1)? 1.0: 0.0;
  /* return the trait value */
  return T * by * exp (age * C);
}


int
age_dep_iterate (age_dep_params_t * data, unsigned int tries)
{
  /* main driver routine */
  /* number of bytes for female frequencies */
  size_t geno = data->age_dep_data->geno;
  size_t genosize = geno * sizeof (double);
  /* female frequencies are equal to male frequencies at birth (before
     selection) */
  double ffreqs[geno];
  if (ffreqs == NULL)
    error (ENOMEM, ENOMEM, nullmsg, __LINE__);
  /* do not set!  Use memcpy (we need to alter male frequencies
     (selection) without altering female frequencies) */
  memmove (ffreqs, data->freqs->freqs[0], genosize);
  /* for (int i = 0; i < geno; i++) */
  /*   ffreqs[i] = data->freqs->freqs[0][i]; */

#ifdef PRMTABLE
  age_dep_pr_mfreqs (data);
#endif  /* PRMTABLE */

  /* natural selection: */
  age_dep_ns (data);

  /* normalized mating table with new frequencies */
  age_dep_norm_mtable (ffreqs, data);

#ifdef PRMTABLE
  age_dep_pr_mtable (data);
#endif  /* PRMTABLE */

  double * newfreqs;
  /* mutate here */
  /* i.e. get the new frequency of 0-year-olds using
     recombination; */
  newfreqs = rec_mating (data->age_dep_data);
  /* return block */  
  {         
    if (sim_stop_ck (data->freqs->freqs[0], newfreqs, GENO, TOL) == 0)
      {
    /* if we have converged, stop the iterations and handle the data */
    age_dep_sim_out (data, stdout);
    return 0;
      }
    else if (tries > MAXTRIES)
      return ERANGE;
    else
      {

    /* advance generations */
    for (int j = age_max - 1; j < 0; j--)
      memmove (data->freqs->freqs[j],
          data->freqs->freqs[j-1],
          genosize);

    /* advance the first age-class */
    memmove (data->freqs->freqs[0], newfreqs, genosize);

    return 1;
      }
  }
}

void
age_dep_ns (age_dep_params_t * data)
{
  /* calculate the new frequency of genotypes given additive fitness
     and selection coefficient s */
  size_t geno = data->age_dep_data->geno;
  double w[geno];
  double wbar, dtheta, ttheta, dcond, tcond;
  double t, cond;

  /* fitness parameters */
  double mu, nu;
  mu = data->wparams[0];
  nu = data->wparams[1];  

  /* calculate fitness */
  for (int j = 0; j < age_max; j++)
    {
      int i;
      for (i = 0; i < geno; i++)
    {
      /* calculate male trait: */
      t = age_dep_trait(j, i, data->by);
      /* calculate condition: */
      cond = (double) bits_popcount (bits_extract(0, CLOCI, i));

      /* trait-based fitness term */
      dtheta = data->theta - t;
      ttheta = (dtheta * dtheta) / (2.0 * nu * nu);

      /* condition-based fitness term */
      dcond = CLOCI - cond;
      tcond = (dcond * dcond) / (2.0 * mu * mu);

      /* calculate male fitness */
      w[i] = 1 + exp(-tcond) - exp(-ttheta);
    }   

      /* calculate mean fitness */
      /* as long as we calculate wbar before altering any values of
     freqs[], we're safe */
      wbar = gen_mean (data->freqs->freqs[j], w, geno);
      for (i = 0; i < geno; i++)
    data->freqs->freqs[j][i] = 
      (data->freqs->freqs[j][i] * w[i]) / wbar;
    }
}

void
age_dep_norm_mtable (double * ffreqs, age_dep_params_t * params)
{
  /* this function produces a single mating table that forms the input
     for recombination () */

  /* i is female genotype; j is male genotype; k is male age */
  int i,j,k;
  double norm_denom;
  double trait;
  size_t geno = params->age_dep_data->geno;

  for (i = 0; i < geno; i++)
    {
      double norm_mtable[geno];
      /* initialize the denominator: */
      norm_denom = 0.0;

      /* find the probability of mating and add it to the denominator */
      for (j = 0; j < geno; j++)
    {
      /* initialize entry: */
      norm_mtable[j] = 0.0;
      for (k = 0; k < age_max; k++)
        {
          trait = age_dep_trait (k, j, params->by);
          norm_mtable[j] +=
        age_dep_pmate (trait, i, params->bp, params->ba)
        * (params->freqs->freqs)[k][j];
        }
      norm_denom += norm_mtable[j];
    }

      /* now calculate entry (i,j) */
      for (j = 0; j < geno; j++)
    params->age_dep_data->mtable[i][j]
      = (ffreqs[i] * norm_mtable[j]) / norm_denom;
    }
}

My current suspicion is the array newfreqs: I can't memmove, memcpy or assign a stack variable then hope it will persist, can I? rec_mating() returns double *.

© Stack Overflow or respective owner

Related posts about c

    Related posts about malloc