Valgrind error, uninitialized value

1.1k Views Asked by At

I created a C++ templated "sample" function which uses Boost random number generators to sample from any object that provides a multinomial distribution as an iterable object.

/** Sample a value from a multinomial law with coefficient of modalities provided */
template<typename T>
int sample(const T& proportion)
{
  boost::random::uniform_real_distribution<> uni(0.,
                                                 1.);
  boost::variate_generator<boost::random::mt19937&,
                           boost::random::uniform_real_distribution<> > generator(rng_,
                                                                                  uni);
  Real x = generator();
  Real cumProb = 0.; // cumulative probability
  int index = 0;

  for(typename T::const_iterator it = proportion.begin();
      it != proportion.end();
      ++it)
  {
    cumProb += *it;
    if (x < cumProb)
    {
      return index;
    }
    ++index;
  }
  return -1; // to accelerate sampling, no check have been computed on modalities to verify that is it actually a probability distribution
};

When I call this using an Eigen vector for example (on which I have added an iterator), I get the following error in Valgrind:

==4917== Conditional jump or move depends on uninitialised value(s)
==4917==    at 0xD7B0A3C: int mixt::MultinomialStatistic::sample<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, -1, -1, false> >(Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, -1, -1, false> const&) (mixt_MultinomialStatistic.h:76)
==4917==    by 0xD7B0538: mixt::ClassSampler::sampleIndividual(int) (mixt_ClassSampler.cpp:63)
==4917==    by 0xD7ADBE6: mixt::IMixtureComposerBase::sStep(int) (mixt_IMixtureComposerBase.cpp:94)
==4917==    by 0xD7ADAF0: mixt::IMixtureComposerBase::sStep() (mixt_IMixtureComposerBase.cpp:68)
==4917==    by 0xD7AC3DE: mixt::SemStrategy::run() (mixt_SEMStrategy.cpp:83)
==4917==    by 0xD74F742: mixtCompCluster(Rcpp::Vector<19, Rcpp::PreserveStorage>, Rcpp::Vector<19, Rcpp::PreserveStorage>, int, double) (mixtCompCluster.cpp:123)
==4917==    by 0xD749A61: RMixtComp_mixtCompCluster (RcppExports.cpp:18)
==4917==    by 0x4F0ADE7: ??? (in /usr/lib/R/lib/libR.so)
==4917==    by 0x4F4981A: Rf_eval (in /usr/lib/R/lib/libR.so)
==4917==    by 0x4F4B92F: ??? (in /usr/lib/R/lib/libR.so)
==4917==    by 0x4F49622: Rf_eval (in /usr/lib/R/lib/libR.so)
==4917==    by 0x4F4A93E: Rf_applyClosure (in /usr/lib/R/lib/libR.so)
==4917== 

The line mixt_MultinomialStatistic.h:76 corresponds to if (x < cumProb). It seems to me that both x and cumProb are defined at this point. How can I debug this ?

EDIT

As suggested by Beta in the comments, I added the following dummy code:

if (x < 1000.)
{}
if (-1000. < cumProb)
{}
if (x < cumProb)
{ ...

And I still get the error reported for the line if (x < cumProb).

When lauching valgrind with the option --track-origins=yes, I get the following indication

==10074==  Uninitialised value was created by a stack allocation

pointing to the instruction:

cumProb += *it;
1

There are 1 best solutions below

0
On

I faced a somewhat similar question when searching my (unit test) code for uninitialized values and found out that Eigen matrices' (and vectors') values don't get initialized in their default constructors. I had such a vector in a struct and eventually got rid of the problem using a statement à la:

struct MyStruct {
  Eigen::Vector2f myVector;
};

MyStruct myStruct{};  // Does not initialize myVector's values!
std::cout << "myVec = " << myStruct.myVector << std::endl; // Causes valgrind to warn about uninitialized variables
myStruct.myVector = Eigen::Vector2f(0.0f, 0.0f);
std::cout << "myVecInit = " << myStruct.myVector << std::endl; // No valgrind warning

Note that I had a hard time debugging this because when launching the unit test with gdb the vector would happen to contain zeros though uninitialized.