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