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 *.