valgrind:无效写入
在以下代码中:
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 是一个向量
。
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<<...) 永远不会被打印。那么根据 valgrind 的说法,invLarvalResources 似乎被释放了?从代码来看,情况似乎并非如此,在这种情况下,valgrind 不应该抱怨之前对 invLarvalResources 的读取吗?
那么 valgrind 在这一点上是完全错误的还是有其他原因?在没有 valgrind 的情况下运行我没有遇到这个问题,但我确实得到了一个奇怪的数值结果,这在隔离的单元测试中找不到。在解决另一个错误之前,我还遇到了 SIGSEGV(我相当确定该错误不应该导致 SIGSEGV)。
构建标志是 -g -rdynamic,编译器是通过 ccache 的 gcc 4.6.1。如果您想要完整的源代码,我将非常乐意向您指出: svn co <a href="http://openmalaria.googlecode.com/svn/branches/vec-lifecycle" rel="nofollow">http ://openmalaria.googlecode.com/svn/branches/vec-lifecycle
任何帮助将不胜感激!
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*) (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)
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!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
那里有相当多的代码...
快速浏览一下,就会发现
invLarvalResources
是对由 a 拥有的vector
的引用MosqLifeCycleParams
。发生的情况是,您将
MosquitoTransmission
按值传递给ResourceFitter
构造函数。当该对象被销毁时(即构造函数返回后),它会销毁其
MosqLifeCycleParams
,而 MosqLifeCycleParams 又恰好拥有您刚刚存储引用的向量。欢闹随之而来。
您需要更加小心引用和所有权(包括返回对私有变量的非常量引用的习惯。这使它们有效地公开。)
道德:当您认为在工具中发现了错误时,它很可能是你的代码。
That's quite a bunch of code you've got there...
A quick glance reveals that
invLarvalResources
is a reference to avector
owned by aMosqLifeCycleParams
.What's happening is that you're passing a
MosquitoTransmission
by value to yourResourceFitter
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 有时可能会出错,但主要与内存泄漏有关。
就您而言,很可能存在内存处理错误。不幸的是,我不确定人们可以仅用您发布的示例代码来回答。
基本上,valgrind 抱怨你的程序试图将 8 个字节的数据写入“最近”以某种方式释放的位置。
这是输出列表中的第一个 valgrind 错误吗?如果没有,请尝试关注您收到的第一个 valgrind 错误/警告:就像编译器输出一样,最后一个错误通常是第一个错误的结果,有时是在完全不同的地方。
请注意“未初始化值”警告,这些警告有时看起来无害,但实际上可能会导致您出现最奇怪的错误。
祝你好运 :)
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 :)
在 SpeciesModel.cpp 的第 391 行,您正在以某种方式(可能是间接地)销毁 MosquiteTransmission 类型的对象,如下所示:
然后您就在之后以某种方式将该对象以某种方式传递给函数,如下所示:
这可能是由于到过时的引用、指针或迭代器。
请注意:
At line 391 of SpeciesModel.cpp you are destroying somehow (maybe indirectly) an object of type MosquiteTransmission, as indicated by:
You are then just after that somehow passing this object in some way to a function, as indicated by:
This can be due to an outdated reference, pointer or iterator.
Note that: