#c #c 11 #smart-pointers
#c #c 11 #интеллектуальные указатели
Вопрос:
Я новичок в использовании интеллектуальных указателей C . Я хотел использовать их в одном большом проекте, над которым я работаю, но я получаю следующую ошибку:
==21819== Invalid free() / delete / delete[] / realloc()
==21819== at 0x4838E7B: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==21819== by 0x188692: std::_Sp_counted_ptr<std::vector<double, std::allocator<double> >*, (__gnu_cxx::_Lock_policy)2>::_M_dispose() (shared_ptr_base.h:377)
==21819== by 0x12F1C9: std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() (shared_ptr_base.h:155)
==21819== by 0x12E724: std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() (shared_ptr_base.h:706)
==21819== by 0x1406D9: std::__shared_ptr<std::vector<double, std::allocator<double> >, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() (shared_ptr_base.h:1145)
==21819== by 0x14071B: std::shared_ptr<std::vector<double, std::allocator<double> > >::~shared_ptr() (shared_ptr.h:103)
==21819== by 0x1CAB5A: myProg::LearningSequence::optimize(myProg::ErrorFunctionamp;, std::basic_ofstream<char, std::char_traits<char> >*) (LearningSequence.cpp:60)
==21819== by 0x12DD6A: main (myScript_1_2.cpp:107)
==21819== Address 0xb2b90d8 is 24 bytes inside a block of size 48 alloc'd
==21819== at 0x4837DBF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==21819== by 0x1331C8: __gnu_cxx::new_allocator<std::_Sp_counted_ptr_inplace<myProg::RandomSolution, std::allocator<myProg::RandomSolution>, (__gnu_cxx::_Lock_policy)2> >::allocate(unsigned long, void const*) (new_allocator.h:111)
==21819== by 0x132BA0: std::allocator_traits<std::allocator<std::_Sp_counted_ptr_inplace<myProg::RandomSolution, std::allocator<myProg::RandomSolution>, (__gnu_cxx::_Lock_policy)2> > >::allocate(std::allocator<std::_Sp_counted_ptr_inplace<myProg::RandomSolution, std::allocator<myProg::RandomSolution>, (__gnu_cxx::_Lock_policy)2> >amp;, unsigned long) (alloc_traits.h:436)
==21819== by 0x1320E9: std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<myProg::RandomSolution, std::allocator<myProg::RandomSolution>, (__gnu_cxx::_Lock_policy)2> > > std::__allocate_guarded<std::allocator<std::_Sp_counted_ptr_inplace<myProg::RandomSolution, std::allocator<myProg::RandomSolution>, (__gnu_cxx::_Lock_policy)2> > >(std::allocator<std::_Sp_counted_ptr_inplace<myProg::RandomSolution, std::allocator<myProg::RandomSolution>, (__gnu_cxx::_Lock_policy)2> >amp;) (allocated_ptr.h:97)
==21819== by 0x131988: std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<myProg::RandomSolution, std::allocator<myProg::RandomSolution>>(std::_Sp_make_shared_tag, myProg::RandomSolution*, std::allocator<myProg::RandomSolution> constamp;) (shared_ptr_base.h:654)
==21819== by 0x131206: std::__shared_ptr<myProg::RandomSolution, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<myProg::RandomSolution>>(std::_Sp_make_shared_tag, std::allocator<myProg::RandomSolution> constamp;) (shared_ptr_base.h:1322)
==21819== by 0x130784: std::shared_ptr<myProg::RandomSolution>::shared_ptr<std::allocator<myProg::RandomSolution>>(std::_Sp_make_shared_tag, std::allocator<myProg::RandomSolution> constamp;) (shared_ptr.h:360)
==21819== by 0x12FA99: std::shared_ptr<myProg::RandomSolution> std::allocate_shared<myProg::RandomSolution, std::allocator<myProg::RandomSolution>>(std::allocator<myProg::RandomSolution> constamp;) (shared_ptr.h:707)
==21819== by 0x12EE24: std::shared_ptr<myProg::RandomSolution> std::make_shared<myProg::RandomSolution>() (shared_ptr.h:723)
==21819== by 0x12DB48: main (myScript_1_2.cpp:86)
Меня это действительно смущает, потому что в строке 86 есть std::shared_ptr
созданный.
86 std::shared_ptr<myProg::LearningMethod> new_learning_method = std::make_shared<myProg::RandomSolution>();
learning_sequence.add_learning_method( new_learning_method );
std::shared_ptr<myProg::LearningMethod> new_learning_method2 = std::make_shared<myProg::ParticleSwarm>(myProg::ParticleSwarm(amp;domain_bounds,
1.711897,
1.711897,
0.711897,
0.5,
0.3,
0.7,
n_particles_swarm,
max_n_iters_swarm) );
// learning_sequence.add_learning_method( new_learning_method2 );
std::shared_ptr<myProg::LearningMethod> new_learning_method3 = std::make_shared<myProg::LevenbergMarquardt>(l4n::LevenbergMarquardt(max_n_iters_gradient_lm, batch_size, prec_lm ) );
learning_sequence.add_learning_method( new_learning_method3 );
/* Complex Optimization */
107 learning_sequence.optimize(mse1); // Network training
Функция optimize()
выглядит следующим образом:
void LearningSequence::optimize(myProg::ErrorFunction amp;ef, std::ofstream *ofs) {
double error = ef.eval();
double the_best_error = error;
int mcycles = this->max_number_of_cycles, cycle_idx = 0;
std::shared_ptr<std::vector<double>> best_params = std::make_shared<std::vector<double>>(this->best_parameters);
while( error > this->tol amp;amp; mcycles != 0){
mcycles--;
cycle_idx ;
for( auto m: this->learning_sequence ){
m->optimize( ef, ofs );
error = ef.eval(m->get_parameters());
ef.get_network_instance()->copy_parameter_space(m->get_parameters());
if( error < the_best_error ){
the_best_error = error;
this->best_parameters = *ef.get_parameters();
}
if( error <= this->tol ){
ef.get_network_instance()->copy_parameter_space( best_params );
return;
}
}
COUT_DEBUG("Cycle: " << cycle_idx << ", the lowest error: " << the_best_error << std::endl );
}
ef.get_network_instance()->copy_parameter_space( best_params );
}
Ошибка далее возникает в функции eval()
:
double MSE::eval(std::shared_ptr<std::vector<double>> weights,
bool denormalize_data,
bool verbose) {
return this->eval_on_data_set(this->ds,
nullptr,
weights,
denormalize_data,
verbose);
puts("END OF EVAL()");
}
which calls eval_on_data_set()
:
double MSE::eval_on_data_set(myProg::DataSet* data_set,
std::ofstream* results_file_path,
std::shared_ptr<std::vector<double>> weights,
bool denormalize_data,
bool verbose) {
size_t dim_in = data_set->get_input_dim();
size_t dim_out = data_set->get_output_dim();
double error = 0.0, val, output_norm = 0;
std::vector<std::pair<std::vector<double>, std::vector<double>>>* data = data_set->get_data();
size_t n_elements = data->size();
std::vector<std::vector<double>> outputs(data->size());
std::vector<double> output(dim_out);
if (verbose) {
COUT_DEBUG("Evaluation of the error function MSE on the given data-set" << std::endl);
COUT_DEBUG(R_ALIGN << "[Element index]" << " "
<< R_ALIGN << "[Input]" << " "
<< R_ALIGN << "[Real output]" << " "
<< R_ALIGN << "[Predicted output]" << " "
<< R_ALIGN << "[Absolute error]" << " "
<< R_ALIGN << "[Relative error %]"
<< std::endl);
}
if (results_file_path) {
*results_file_path << R_ALIGN << "[Element index]" << " "
<< R_ALIGN << "[Input]" << " "
<< R_ALIGN << "[Real output]" << " "
<< R_ALIGN << "[Predicted output]" << " "
<< R_ALIGN << "[Abs. error]" << " "
<< R_ALIGN << "[Rel. error %]"
<< std::endl;
}
for (auto i = 0; i < data->size(); i ) { // Iterate through every element in the test set
/* Compute the net output and store it into 'output' variable */
this->net->eval_single(data->at(i).first,
output,
weights);
outputs.at(i) = output;
}
double denormalized_output;
double denormalized_real_input;
double denormalized_real_output;
for (auto i = 0; i < data->size(); i ) {
/* Compute difference for every element of the output vector */
#ifdef DEBUG
std::stringstream ss_input;
std::string separator = "";
for (auto j = 0; j < dim_in; j ) {
if(denormalize_data) {
denormalized_real_input = data_set->get_normalization_strategy()->de_normalize(data->at(i).first.at(j));
} else {
denormalized_real_input = data->at(i).first.at(j);
}
ss_input << separator << denormalized_real_input;
separator = ",";
}
if(denormalize_data) {
denormalized_real_input = data_set->get_normalization_strategy()->de_normalize(data->at(i).first.back());
} else {
denormalized_real_input = data->at(i).first.back();
}
std::stringstream ss_real_output;
std::stringstream ss_predicted_output;
#endif
double loc_error = 0;
output_norm = 0;
separator = "";
for (size_t j = 0; j < dim_out; j) {
if (denormalize_data) {
denormalized_real_output = data_set->get_normalization_strategy()->de_normalize(data->at(i).second.at(j));
denormalized_output = data_set->get_normalization_strategy()->de_normalize(outputs.at(i).at(j));
} else {
denormalized_real_output = data->at(i).second.at(j);
denormalized_output = outputs.at(i).at(j);
}
#ifdef DEBUG
ss_real_output << separator << denormalized_real_output;
ss_predicted_output << separator << denormalized_output;
separator = ",";
#endif
val = denormalized_output - denormalized_real_output;
loc_error = val * val;
error = loc_error;
output_norm = denormalized_output * denormalized_output;
}
#ifdef DEBUG
std::stringstream ss_ind;
ss_ind << "[" << i << "]";
if (verbose) {
COUT_DEBUG(R_ALIGN << ss_ind.str() << " "
<< R_ALIGN << ss_input.str() << " "
<< R_ALIGN << ss_real_output.str() << " "
<< R_ALIGN << ss_predicted_output.str() << " "
<< R_ALIGN << std::sqrt(loc_error) << " "
<< R_ALIGN
<< 200.0 * std::sqrt(loc_error) / (std::sqrt(loc_error) std::sqrt(output_norm))
<< std::endl);
}
if (results_file_path) {
*results_file_path << R_ALIGN << ss_ind.str() << " "
<< R_ALIGN << ss_input.str() << " "
<< R_ALIGN << ss_real_output.str() << " "
<< R_ALIGN << ss_predicted_output.str() << " "
<< R_ALIGN << std::sqrt(loc_error) << " "
<< R_ALIGN
<< 200.0 * std::sqrt(loc_error) / (std::sqrt(loc_error) std::sqrt(output_norm))
<< std::endl;
}
#endif
}
double result = std::sqrt(error) / n_elements;
if (verbose) {
COUT_DEBUG("MSE = " << result << std::endl);
}
if (results_file_path) {
*results_file_path << "MSE = " << result << std::endl;
}
puts("END OF EVAL_ON_DATA_SET");
return resu<
}
Самое странное, что перед завершением работы программы выводится КОНЕЦ EVAL_ON_DATA_SET, а КОНЕЦ EVAL() — нет, т.е. программа завершает работу с завершением eval_on_data_set()
функции.
Есть ли какой-либо способ выяснить, что происходит?
Большое вам спасибо за любой совет.
Редактировать
Я попытался использовать средство очистки памяти в соответствии с советом xaxxon, и вот результат:
=================================================================
==6515==ERROR: AddressSanitizer: alloc-dealloc-mismatch (INVALID vs operator delete) on 0x604000001ee8
#0 0x7f2ad3a55118 in operator delete(void*, unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.5 0xf1118)
#1 0x5589562f445b in std::_Sp_counted_ptr<std::vector<double, std::allocator<double> >*, (__gnu_cxx::_Lock_policy)2>::_M_dispose() /usr/include/c /8/bits/shared_ptr_base.h:377
#2 0x558956239de2 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() /usr/include/c /8/bits/shared_ptr_base.h:155
#3 0x5589562386dd in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() /usr/include/c /8/bits/shared_ptr_base.h:706
#4 0x5589562383f1 in std::__shared_ptr<std::vector<double, std::allocator<double> >, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() /usr/include/c /8/bits/shared_ptr_base.h:1145
#5 0x55895623840d in std::shared_ptr<std::vector<double, std::allocator<double> > >::~shared_ptr() /usr/include/c /8/bits/shared_ptr.h:103
#6 0x558956393484 in myProg::LearningSequence::optimize(myProg::ErrorFunctionamp;, std::basic_ofstream<char, std::char_traits<char> >*) /home/martin/myProg/src/LearningMethods/LearningSequence.cpp:60
#7 0x55895623685e in main /home/martin/myProg/src/examples/simulator_1_2.cpp:108
#8 0x7f2ad31cf09a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6 0x2409a)
#9 0x558956235669 in _start (/home/martin/myProg/build/bin/examples/simulator_1_2 0x4c669)
0x604000001ee8 is located 24 bytes inside of 48-byte region [0x604000001ed0,0x604000001f00)
allocated by thread T0 here:
#0 0x7f2ad3a53b60 in operator new(unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.5 0xefb60)
#1 0x558956241b31 in __gnu_cxx::new_allocator<std::_Sp_counted_ptr_inplace<myProg::RandomSolution, std::allocator<myProg::RandomSolution>, (__gnu_cxx::_Lock_policy)2> >::allocate(unsigned long, void const*) (/home/martin/myProg/build/bin/examples/simulator_1_2 0x58b31)
#2 0x55895624128e in std::allocator_traits<std::allocator<std::_Sp_counted_ptr_inplace<myProg::RandomSolution, std::allocator<myProg::RandomSolution>, (__gnu_cxx::_Lock_policy)2> > >::allocate(std::allocator<std::_Sp_counted_ptr_inplace<myProg::RandomSolution, std::allocator<myProg::RandomSolution>, (__gnu_cxx::_Lock_policy)2> >amp;, unsigned long) (/home/martin/myProg/build/bin/examples/simulator_1_2 0x5828e)
#3 0x558956240065 in std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<myProg::RandomSolution, std::allocator<myProg::RandomSolution>, (__gnu_cxx::_Lock_policy)2> > > std::__allocate_guarded<std::allocator<std::_Sp_counted_ptr_inplace<myProg::RandomSolution, std::allocator<myProg::RandomSolution>, (__gnu_cxx::_Lock_policy)2> > >(std::allocator<std::_Sp_counted_ptr_inplace<myProg::RandomSolution, std::allocator<myProg::RandomSolution>, (__gnu_cxx::_Lock_policy)2> >amp;) (/home/martin/myProg/build/bin/examples/simulator_1_2 0x57065)
#4 0x55895623f2ac in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<myProg::RandomSolution, std::allocator<myProg::RandomSolution>>(std::_Sp_make_shared_tag, myProg::RandomSolution*, std::allocator<myProg::RandomSolution> constamp;) (/home/martin/myProg/build/bin/examples/simulator_1_2 0x562ac)
#5 0x55895623e4d8 in std::__shared_ptr<myProg::RandomSolution, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<myProg::RandomSolution>>(std::_Sp_make_shared_tag, std::allocator<myProg::RandomSolution> constamp;) (/home/martin/myProg/build/bin/examples/simulator_1_2 0x554d8)
#6 0x55895623cb90 in std::shared_ptr<myProg::RandomSolution>::shared_ptr<std::allocator<myProg::RandomSolution>>(std::_Sp_make_shared_tag, std::allocator<myProg::RandomSolution> constamp;) (/home/martin/myProg/build/bin/examples/simulator_1_2 0x53b90)
#7 0x55895623ade5 in std::shared_ptr<myProg::RandomSolution> std::allocate_shared<myProg::RandomSolution, std::allocator<myProg::RandomSolution>>(std::allocator<myProg::RandomSolution> constamp;) (/home/martin/myProg/build/bin/examples/simulator_1_2 0x51de5)
#8 0x5589562394a5 in std::shared_ptr<myProg::RandomSolution> std::make_shared<myProg::RandomSolution>() (/home/martin/myProg/build/bin/examples/simulator_1_2 0x504a5)
#9 0x558956236538 in main /home/martin/myProg/src/examples/simulator_1_2.cpp:86
#10 0x7f2ad31cf09a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6 0x2409a)
SUMMARY: AddressSanitizer: alloc-dealloc-mismatch (/usr/lib/x86_64-linux-gnu/libasan.so.5 0xf1118) in operator delete(void*, unsigned long)
==6515==HINT: if you don't care about these errors you may set ASAN_OPTIONS=alloc_dealloc_mismatch=0
==6515==ABORTING
Строку 86 с объявлением общего указателя можно увидеть выше, а также функцию оптимизации… Итак, я не уверен, смогу ли я получить больше информации таким образом.
Комментарии:
1. Вам действительно нужно показать все строки между тем местом, где вы создаете shared_ptr и где происходит сбой вашей программы. И точно укажите, что происходит внутри любых функций, которые вы вызываете. Скорее всего, в процессе преобразования вы могли вызвать
delete
необработанный указатель shared_ptr. Или у вас может быть неопределенное поведение / повреждение кучи из-за переполнения буфера где-нибудь. Это очень трудно определить, основываясь на скудной информации, которую вы предоставили до сих пор.2. @paddy Что ж, я попытался предоставить больше кода — если вам нужна дополнительная информация, я ее дополню.
3. Сообщения об ошибках пахнут как ошибка повреждения памяти, которую, как известно, трудно отследить. Вам нужно выполнить поиск доступа за пределы в части кода, не связанной с частью, которая выдает вам ошибки.
4. Я настоятельно рекомендую добавить флаг компилятора -fsanitize=address и запустить его снова
5. Кажется, что что-то перезаписывает память, которая принадлежит
best_params
. Моим следующим шагом было бы запустить под gdb. Сразу послеbest_params
инициализации ставится точка останова. Когда вы доберетесь туда, установите аппаратные контрольные точки (watch
команда) дляbest_params
себя, а также для памяти, на которую она указывает.continue
затем каждый раз, когда запускается аппаратная контрольная точка, смотрите, имеет ли смысл изменять вызывающий кодbest_params
или его общий блок.