在以下代码中:
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;
}
}
这是ResourceFitter.cpp的几行。第380行是最后一行代码(在invLarvalResources中分配)。 invLarvalResources是vector<double>
。
valgrind抱怨:
==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*) (ResourceFitter.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)
调试行(cout&lt;&lt; ...)永远不会打印出来。那么从valgrind看来,似乎释放了invLarvalResources?从查看看起来不是这样的代码,在那种情况下,不应该valgrind抱怨以前对invLarvalResources的读取?
对于valgrind来说,这是完全错误还是其他事情发生了?在没有valgrind的情况下运行我没有遇到这个问题,但我确实得到了一个奇怪的数值结果,这在单独的单元测试中找不到。在解决另一个bug之前我也遇到了一个SIGSEGV(我当时肯定不应该导致一个SIGSEGV)。
构建标志是-g -rdynamic,编译器是通过ccache的gcc 4.6.1。如果您需要完整的资源,我将非常乐意为您指出:svn co http://openmalaria.googlecode.com/svn/branches/vec-lifecycle
非常感谢任何帮助!
答案 0 :(得分:4)
你有很多代码......
快速浏览一下,invLarvalResources
是<{1}}所拥有的vector
的参考。
正在发生的事情是您将MosqLifeCycleParams
按值传递给MosquitoTransmission
构造函数。
当该对象被销毁时 - 即一旦构造函数返回 - 它就会销毁它的ResourceFitter
,而MosqLifeCycleParams
又碰巧拥有你刚刚存储了引用的向量。
随之欢闹。
您需要更加谨慎地使用引用和所有权(包括将非const引用返回私有变量的习惯。这使得它们实际上是公开的。)
道德:当你认为你在工具中发现了一个错误时,它很可能是你代码中的一个错误。答案 1 :(得分:1)
valgrind
有时可能是错误的,但主要是关于内存泄漏。
在您的情况下,您很可能遇到内存处理错误。不幸的是,我不确定只能回答您发布的示例代码。
基本上,valgrind抱怨你的程序试图将8个字节的数据写入一个“最近”以某种方式解除分配的位置。
它是输出列表中的第一个valgrind错误吗?如果没有,请尝试关注你得到的第一个valgrind错误/警告:就像编译器输出一样,最后的错误通常是第一个错误的结果,有时是在一个完全不同的地方。
谨防“未初始化的值”警告,这些警告有时似乎无害,但实际上可能会导致您发生最奇怪的错误。
祝你好运:)答案 2 :(得分:0)
在SpeciesModel.cpp的第391行,您正在以某种方式(可能是间接地)销毁MosquiteTransmission类型的对象,如下所示:
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)
然后你就是以某种方式将这个对象以某种方式传递给一个函数,如下所示:
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)
这可能是由于过时的引用,指针或迭代器造成的。
请注意: