valgrind: неверная запись - PullRequest
       12

valgrind: неверная запись

0 голосов
/ 26 августа 2011

В следующем коде:

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 << ...) никогда не печатаются.Так из чего говорит valgrind, кажется, что invLarvalResources был освобожден?Взглянув на код, который, кажется, не соответствует действительности, и в этом случае не должен ли valgrind пожаловаться на предыдущие чтения invLarvalResources? </p>

Так что valgrind просто ошибается в этом или что-то еще происходит?на?Работая без valgrind, я не сталкиваюсь с этой проблемой, но получаю странный числовой результат, которого нет в изолированных модульных тестах.Я также столкнулся с SIGSEGV перед тем, как решить другую ошибку (которую я был уверен, что не должен был вызывать SIGSEGV).

Флажки сборки -g -rdynamic, компилятор gcc 4.6.1 через ccacheЕсли вам нужны полные источники, я буду более чем рад указать вам: svn co http://openmalaria.googlecode.com/svn/branches/vec-lifecycle

Любая помощь будет принята с благодарностью!

Ответы [ 3 ]

4 голосов
/ 26 августа 2011

Это довольно много кода у вас есть ...

Быстрый взгляд показывает, что invLarvalResources является ссылкой на vector, принадлежащим MosqLifeCycleParams.

Что происходит, так это то, что вы передаете MosquitoTransmission по значению в ваш ResourceFitter конструктор. Когда этот объект уничтожается, т. Е. Как только возвращается конструктор, он уничтожает свой MosqLifeCycleParams, который, в свою очередь, принадлежал вектору, на который вы только что сохранили ссылку.
Веселье наступает.

Вы должны быть более осторожны со ссылками и владельцем (включая вашу привычку возвращать неконстантные ссылки на частные переменные. Это делает их эффективно открытыми.)

Мораль: когда вы думаете, что нашли ошибку в инструменте, это, скорее всего, ошибка в вашем коде.

1 голос
/ 26 августа 2011

valgrind иногда может ошибаться, но в основном из-за утечек памяти.

В вашем случае очень вероятно, что у вас есть ошибка обработки памяти. К сожалению, я не уверен, что можно ответить, просто отправив пример кода.

По сути, valgrind жалуется, что ваша программа пытается записать 8 байтов данных в место, которое было как-то "недавно" освобождено.

Это ваша первая ошибка valgrind в списке вывода? Если нет, попробуйте сосредоточиться на первой полученной ошибке / предупреждении valgrind: точно так же как выходные данные компилятора, последние ошибки очень часто являются результатом первой ошибки, иногда в совершенно другом месте.

Остерегайтесь предупреждений о "неинициализированных значениях", которые иногда могут казаться безвредными, но на самом деле могут привести к самым странным ошибкам.

Удачи:)

0 голосов
/ 26 августа 2011

В строке 391 SpeciesModel.cpp вы каким-то образом (возможно, косвенно) уничтожаете объект типа 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 для проверки вашего процесса
  • Операции над вектором, которые изменяют емкость, лишают законной силы итераторы, ссылки и указатели на элементы, которые были в векторе.
...