开发者

valgrind: invalid write

In the following code:

void ResourceFitter::copyToLarvalResources( const gsl_vector* input ){
    assert( input->size == invLarvalResources.size() );
    if( invLarvalResources.size() != 365 ){
        cout<<"error: iLR.size(): "<<invLarvalResources.size()<<endl;
        exit(21);
    }
    // inverting larval resources may help fitting algorithm, so we do that here:
    for( size_t i=0; i<invLarvalResources.size(); ++i ){
        if( i >= 365 ){
            cout<<"error: i="<<i<<endl;
            exit(22);
        }
        double val = gsl_vector_get( input, i );
        invLarvalResources[i] = 1.0 / val;
    }
}

This is a few lines from ResourceFitter.cpp. Line 380 is the last line of code (assigning in invLarvalResources). invLarvalResources is a vector<double>.

valgrind complains:

==30152== Invalid write of size 8
==30152==    at 0x8ED3E5: OM::Transmission::Vector::ResourceFitter::copyToLarvalResources(gsl_vector const*) (ResourceFitter.cpp:380)
==30152==    by 0x8ECE99: OM::Transmission::Vector::ResourceFitter::sampler(gsl_vector const*) (Resou开发者_StackOverflow社区rceFitter.cpp:334)
==30152==    by 0x8EB64D: OM::Transmission::Vector::ResourceFitter_minimise_sampler(gsl_vector const*, void*) (ResourceFitter.cpp:88)
==30152==    by 0x4F3249A: ??? (in /usr/lib/libgsl.so.0.16.0)
==30152==    by 0x8ED5C4: OM::util::MultidimMinimiser::MultidimMinimiser(gsl_multimin_fminimizer_type const*, unsigned long, double (*)(gsl_vector const*, void*), void*, gsl_vector*, gsl_vector*) (MultidimSolver.h:71)
==30152==    by 0x8EC45E: OM::Transmission::Vector::ResourceFitter::fit(unsigned long, OM::Transmission::Vector::ResourceFitter::FitMethod, unsigned long) (ResourceFitter.cpp:217)
==30152==    by 0x8EC308: OM::Transmission::Vector::ResourceFitter::fit() (ResourceFitter.cpp:183)
==30152==    by 0x8E474F: OM::Transmission::Vector::SpeciesModel::init2(unsigned long, std::list<OM::Host::Human, std::allocator<OM::Host::Human> > const&, int, double) (SpeciesModel.cpp:393)
==30152==    by 0x8DA29E: OM::Transmission::VectorModel::init2(std::list<OM::Host::Human, std::allocator<OM::Host::Human> > const&, int) (VectorModel.cpp:163)
==30152==    by 0x81C08F: OM::Population::createInitialHumans() (Population.cpp:165)
==30152==    by 0x8172E8: OM::Simulation::start() (Simulation.cpp:120)
==30152==    by 0x816615: main (openMalaria.cpp:53)
==30152==  Address 0x8ca3d10 is 0 bytes inside a block of size 2,920 free'd
==30152==    at 0x4C2658C: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30152==    by 0x822515: __gnu_cxx::new_allocator<double>::deallocate(double*, unsigned long) (new_allocator.h:98)
==30152==    by 0x81FDBB: std::_Vector_base<double, std::allocator<double> >::_M_deallocate(double*, unsigned long) (stl_vector.h:156)
==30152==    by 0x81FC98: std::_Vector_base<double, std::allocator<double> >::~_Vector_base() (stl_vector.h:142)
==30152==    by 0x81E82B: std::vector<double, std::allocator<double> >::~vector() (stl_vector.h:351)
==30152==    by 0x8DB5D2: OM::Transmission::Vector::MosqLifeCycleParams::~MosqLifeCycleParams() (in /home/dhardy/code/openmalaria/build-debug/openMalaria)
==30152==    by 0x8DBA24: OM::Transmission::Vector::MosquitoTransmission::~MosquitoTransmission() (in /home/dhardy/code/openmalaria/build-debug/openMalaria)
==30152==    by 0x8E4719: OM::Transmission::Vector::SpeciesModel::init2(unsigned long, std::list<OM::Host::Human, std::allocator<OM::Host::Human> > const&, int, double) (SpeciesModel.cpp:391)
==30152==    by 0x8DA29E: OM::Transmission::VectorModel::init2(std::list<OM::Host::Human, std::allocator<OM::Host::Human> > const&, int) (VectorModel.cpp:163)
==30152==    by 0x81C08F: OM::Population::createInitialHumans() (Population.cpp:165)
==30152==    by 0x8172E8: OM::Simulation::start() (Simulation.cpp:120)
==30152==    by 0x816615: main (openMalaria.cpp:53)

The debug lines (cout<<...) never get printed. So from what valgrind says it appears that invLarvalResources was freed? From looking at the code that doesn't appear to be the case, and in that case shouldn't valgrind complain about the previous reads to invLarvalResources?

So is valgrind just plain wrong on this or is something else going on? Running without valgrind I don't encounter this problem, but I do get a strange numerical result which isn't found in isolated unit tests. I also encountered a SIGSEGV before solving another bug (which I was moderately sure shouldn't have caused a SIGSEGV).

Build-flags are -g -rdynamic, compiler is gcc 4.6.1 via ccache. If you want full sources, I'll be more than happy to point you to: svn co http://openmalaria.googlecode.com/svn/branches/vec-lifecycle

Any help would be much appreciated!


That's quite a bunch of code you've got there...

A quick glance reveals that invLarvalResources is a reference to a vector owned by a MosqLifeCycleParams.

What's happening is that you're passing a MosquitoTransmission by value to your ResourceFitter constructor. When that object is destroyed - i.e. as soon as the constructor returns - it destroys its MosqLifeCycleParams, which in turn happened to own the vector you just stored a reference to.
Hilarity ensues.

You need to be more careful with references and ownership (including your habit of returning non-const references to private variables. That makes them effectively public.)

Moral: When you think you found a bug in the tool, it's most probably a bug in your code.


valgrind can sometimes be wrong, but mostly about memory leaks.

In your case, it is very likely that you have a memory handling error. Unfortunately, I'm not sure one can answer with just the sample code you posted.

Basically, valgrind complains that your program tries to write 8 bytes of data to a location that was deallocated somehow "recently".

Is it your first valgrind error in the output listing ? If not, try to focus on the first valgrind error/warning that you get: just like compiler output, the last errors are very often the result of a first mistake, sometimes at a completely different place.

Beware of "uninitialized values" warnings which can sometimes seem harmless but can actually lead you to the strangest errors.

Good luck :)


At line 391 of SpeciesModel.cpp you are destroying somehow (maybe indirectly) an object of type MosquiteTransmission, as indicated by:

OM::Transmission::Vector::MosquitoTransmission::~MosquitoTransmission() (in /home/dhardy/code/openmalaria/build-debug/openMalaria)
by 0x8E4719: OM::Transmission::Vector::SpeciesModel::init2(unsigned long, std::list<OM::Host::Human, std::allocator<OM::Host::Human> > const&, int, double) (SpeciesModel.cpp:391)

You are then just after that somehow passing this object in some way to a function, as indicated by:

by 0x8E474F: OM::Transmission::Vector::SpeciesModel::init2(unsigned long, std::list<OM::Host::Human, std::allocator<OM::Host::Human> > const&, int, double) (SpeciesModel.cpp:393)

This can be due to an outdated reference, pointer or iterator.

Note that:

  • valgrind sometimes does not fully get the line numbers right. Make sure you compile with -ggdb3 and use a very revent (svn) valgrind version. A good way is also to use the --db-attach option, which will put you into gdb to inspect your process
  • operations on vector that change the capacity will invalidate iterators, references and pointers to elements that were in the vector.
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜