valgrind:无效写入

发布于 2024-12-01 17:21:30 字数 4585 浏览 1 评论 0原文

在以下代码中:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

不及他 2024-12-08 17:21:30

那里有相当多的代码...

快速浏览一下,就会发现 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 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.

你穿错了嫁妆 2024-12-08 17:21:30

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 :)

[旋木] 2024-12-08 17:21:30

在 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)

这可能是由于到过时的引用、指针或迭代器。

请注意:

  • valgrind 有时无法完全正确地获取行号。确保使用 -ggdb3 进行编译并使用非常 revent (svn) valgrind 版本。一个好的方法是使用 --db-attach 选项,它会让您进入 gdb 来检查
  • 向量上的进程操作,这些操作改变容量将使迭代器、引用和指向向量中元素的指针无效。

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.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文