Boost logo

Boost Users :

Subject: Re: [Boost-users] Mersenne twister problem
From: Matthias Troyer (troyer_at_[hidden])
Date: 2009-09-17 15:45:27


On 17 Sep 2009, at 17:11, ruya wrote:

>
>
> Matthias Troyer-2 wrote:
>>
>>
>> On 16 Sep 2009, at 10:38, ruya wrote:
>>
>>>
>>> SType is not a SearchFunctor. It is a template parameter of
>>> SearchFunctor.
>>> Look, I am not a professional coder or something. I could accept
>>> that my
>>> code has memory leaks, except that I monitored the memory usage and
>>> it is
>>> stable and quite small too. I have three other algorithms using the
>>> same
>>> SearchFunctors and the behavior is as expected and no memory leaks.
>>> As for the complication that my code appears to be to you, how would
>>> you
>>> simplify it? You argued before that you would do it diferently and
>>> avoid for
>>> sure the segmentation fault.
>>>>>
>>>>> SearchFunctor(){
>>>>> memh = MemHandler();
>>>>> generator1 = base_generator_type(MASTER_SEED+13);
>>>>> uni_dist1 = boost::uniform_real<>(0,1);
>>>>> uniEmp = new GeneratorI(generator1, uni_dist1);
>>>>> generator2 = base_generator_type(MASTER_SEED+17);
>>>>> uni_dist2 = boost::uniform_real<>(0,1);
>>>>> uniRes = new GeneratorI(generator2, uni_dist2);
>>>>> }
>>>>> protected:
>>>>> virtual ~SearchFunctor(){}
>>
>> Just look at this code fragment: you allocate memory in the
>> constructor using new and never release it using delete
>>
>>
>
> I probably don't see this leak in the memory usage because only a
> limited
> amount of SearchFunctors are created at the beginning and they live
> for as
> long as the program runs. (I think this makes sense)
> Anyhow, writing the proper destructors doesn't solve my problem, but
> now gdb
> points to immediatly before the creation of any of the
> SearchFunctors. So,
> to remember, I have three SearchFunctors (SFs). In three different
> applications the three of them work as expected. In this particular
> app, the
> SFs were successfully created, then two ran well, and one would give
> a seg
> fault. Now, with the proper destructor in class SearchFunctor, the
> fault
> comes at the time of creation. gdb points to the line where the
> following
> functions is called:
>
>
> functors = vector<SearchF>();
> TL2FunV<TList, SearchF>::FillVector( functors ); //gdb points fault
> here but
> does not go inside
>
> template< typename TList, class SearchFun >
> struct TL2FunV{
> static void FillVector( std::vector< SearchFun >& v){
> typename TList::Head h;
> v.push_back( SearchFun(h) );
> TL2FunV<typename TList::Tail, SearchFun>::FillVector( v );
> }
> };
>
> template< class SearchFun >
> struct TL2FunV< Loki::NullType, SearchFun>{
> static void FillVector( std::vector< SearchFun >& v ){};
> };
>
> Rui
>

Since you use pointers inside your class you also need to write a copy
constructor and assignment operator creating new generators. I now
understand the reason for your crash:

- you create a SearchFunctor, this creates the engine as a member and
the generators through pointers
- you copy the SearchFunctor in the FillVector function. Using the
implicitly generated copy constructor this just copies the pointers
- after copying the original class gets destroyed - including the
random number engine.
- you call the generator, but the engine no longer exists ->
segmentation fault.

Whenever you allocate memory on a constructor you need to provide a
special destructor, copy constructor and assignment operator. Either
add those, or - much easier, just use the following class:

template< class SType, typename MemP >
class SearchFunctor{
protected:
   typedef boost::mt19937 base_generator_type;
   typedef boost::variate_generator<base_generator_type,
boost::uniform_real<> > GeneratorI;
public:

   SearchFunctor()
     : uniEmp(base_generator_type(MASTER_SEED+13),boost::uniform_real<>
(0,1))
     , uniRes(base_generator_type(MASTER_SEED+17),boost::uniform_real<>
(0,1))
   {}

protected:
   virtual ~SearchFunctor(){}

   GeneratorI uniEmp;
   GeneratorI uniRes;
}

Note that I removed the & after the generator type to avoid a problem
with the copy constructor. Better yet, make the generator a static
class member and use the &:

template< class SType, typename MemP >
class SearchFunctor{
protected:
   typedef boost::mt19937 base_generator_type;
   typedef boost::variate_generator<base_generator_type&,
boost::uniform_real<> > GeneratorI;
public:

   SearchFunctor()
     : uniEmp(generator,boost::uniform_real<>(0,1))
     , uniRes(generator,boost::uniform_real<>(0,1))
   {}

protected:
   virtual ~SearchFunctor(){}
   GeneratorI uniEmp;
   GeneratorI uniRes;
private:
   static base_generator_type generator;
}

template< class SType, typename MemP >
typename SearchFunctor< SType, MemP>::base_generator_type
SearchFunctor< SType, MemP>::generator(MASTER_SEED);

Matthias


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net