tesseract-robotics / trajopt

Trajectory Optimization Motion Planner for ROS
394 stars 104 forks source link

Memory Leak #233

Closed mpowelson closed 3 years ago

mpowelson commented 3 years ago

I am trying to track down a memory leak that I am running into when using the Tesseract planner. While I'm not sure if this is the entirety of what I was running into running these valgrind commands on the Tesseract example yields this output which appears to indicate a leak in Trajopt. If I am reading this correctly, we are losing 12 KB per freespace motion planning call.

valgrind --leak-check=full          --show-leak-kinds=all          --track-origins=yes          --verbose          --log-file=valgrind-out.txt          ./tesseract_process_managers_freespace_manager_example 

Abridged output with the "definetly lost" records:

==26068== 448 bytes in 7 blocks are definitely lost in loss record 43 of 64
==26068==    at 0x483BE63: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==26068==    by 0x7A7609D: sco::OSQPModel::addEqCnt(sco::AffExpr const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (osqp_interface.cpp:57)
==26068==    by 0x7A1365B: sco::OptProb::addLinearConstraint(sco::AffExpr const&, sco::ConstraintType) (modeling.cpp:234)
==26068==    by 0x768CB51: trajopt::ConstructProblem(trajopt::ProblemConstructionInfo const&) (problem_description.cpp:493)
==26068==    by 0x65C30B5: tesseract_planning::TrajOptMotionPlanner::solve(tesseract_planning::PlannerRequest const&, tesseract_planning::PlannerResponse&, bool) const (trajopt_motion_planner.cpp:137)
==26068==    by 0x4C35336: tesseract_planning::MotionPlannerTaskGenerator::conditionalProcess(tesseract_planning::TaskInput, unsigned long) const (motion_planner_task_generator.cpp:160)
==26068==    by 0x4BA711D: tesseract_planning::TaskGenerator::assignConditionalTask(tesseract_planning::TaskInput, tf::Task&)::{lambda()#1}::operator()() const (task_generator.cpp:63)
==26068==    by 0x4BA84E9: std::_Function_handler<int (), tesseract_planning::TaskGenerator::assignConditionalTask(tesseract_planning::TaskInput, tf::Task&)::{lambda()#1}>::_M_invoke(std::_Any_data const&) (std_function.h:285)
==26068==    by 0x4BBA29D: std::function<int ()>::operator()() const (std_function.h:688)
==26068==    by 0x4BB5C9E: tf::Executor::_invoke_condition_work(tf::Executor::Worker&, tf::Node*) (executor.hpp:969)
==26068==    by 0x4BB51F1: tf::Executor::_invoke(tf::Executor::Worker&, tf::Node*) (executor.hpp:781)
==26068==    by 0x4BB45C6: tf::Executor::_exploit_task(tf::Executor::Worker&, tf::Node*&) (executor.hpp:533)
==26068== 
==26068== 728 bytes in 13 blocks are definitely lost in loss record 44 of 64
==26068==    at 0x483BE63: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==26068==    by 0x7A75F6E: sco::OSQPModel::addVar(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (osqp_interface.cpp:49)
==26068==    by 0x79EA6F4: sco::Model::addVar(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, double, double) (solver_interface.cpp:103)
==26068==    by 0x7A11752: sco::ConvexObjective::addAbs(sco::AffExpr const&, double) (modeling.cpp:32)
==26068==    by 0x7A21657: sco::cntsToCosts(std::vector<std::shared_ptr<sco::ConvexConstraints>, std::allocator<std::shared_ptr<sco::ConvexConstraints> > > const&, std::vector<double, std::allocator<double> > const&, sco::Model*) (optimizers.cpp:133)
==26068==    by 0x7A256BA: sco::BasicTrustRegionSQP::optimize() (optimizers.cpp:620)
==26068==    by 0x65C326C: tesseract_planning::TrajOptMotionPlanner::solve(tesseract_planning::PlannerRequest const&, tesseract_planning::PlannerResponse&, bool) const (trajopt_motion_planner.cpp:158)
==26068==    by 0x4C35336: tesseract_planning::MotionPlannerTaskGenerator::conditionalProcess(tesseract_planning::TaskInput, unsigned long) const (motion_planner_task_generator.cpp:160)
==26068==    by 0x4BA711D: tesseract_planning::TaskGenerator::assignConditionalTask(tesseract_planning::TaskInput, tf::Task&)::{lambda()#1}::operator()() const (task_generator.cpp:63)
==26068==    by 0x4BA84E9: std::_Function_handler<int (), tesseract_planning::TaskGenerator::assignConditionalTask(tesseract_planning::TaskInput, tf::Task&)::{lambda()#1}>::_M_invoke(std::_Any_data const&) (std_function.h:285)
==26068==    by 0x4BBA29D: std::function<int ()>::operator()() const (std_function.h:688)
==26068==    by 0x4BB5C9E: tf::Executor::_invoke_condition_work(tf::Executor::Worker&, tf::Node*) (executor.hpp:969)
==26068== 
==26068== 728 bytes in 13 blocks are definitely lost in loss record 45 of 64
==26068==    at 0x483BE63: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==26068==    by 0x7A75F6E: sco::OSQPModel::addVar(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (osqp_interface.cpp:49)
==26068==    by 0x79EA6F4: sco::Model::addVar(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, double, double) (solver_interface.cpp:103)
==26068==    by 0x7A117D1: sco::ConvexObjective::addAbs(sco::AffExpr const&, double) (modeling.cpp:33)
==26068==    by 0x7A21657: sco::cntsToCosts(std::vector<std::shared_ptr<sco::ConvexConstraints>, std::allocator<std::shared_ptr<sco::ConvexConstraints> > > const&, std::vector<double, std::allocator<double> > const&, sco::Model*) (optimizers.cpp:133)
==26068==    by 0x7A256BA: sco::BasicTrustRegionSQP::optimize() (optimizers.cpp:620)
==26068==    by 0x65C326C: tesseract_planning::TrajOptMotionPlanner::solve(tesseract_planning::PlannerRequest const&, tesseract_planning::PlannerResponse&, bool) const (trajopt_motion_planner.cpp:158)
==26068==    by 0x4C35336: tesseract_planning::MotionPlannerTaskGenerator::conditionalProcess(tesseract_planning::TaskInput, unsigned long) const (motion_planner_task_generator.cpp:160)
==26068==    by 0x4BA711D: tesseract_planning::TaskGenerator::assignConditionalTask(tesseract_planning::TaskInput, tf::Task&)::{lambda()#1}::operator()() const (task_generator.cpp:63)
==26068==    by 0x4BA84E9: std::_Function_handler<int (), tesseract_planning::TaskGenerator::assignConditionalTask(tesseract_planning::TaskInput, tf::Task&)::{lambda()#1}>::_M_invoke(std::_Any_data const&) (std_function.h:285)
==26068==    by 0x4BBA29D: std::function<int ()>::operator()() const (std_function.h:688)
==26068==    by 0x4BB5C9E: tf::Executor::_invoke_condition_work(tf::Executor::Worker&, tf::Node*) (executor.hpp:969)
==26068== 
==26068== 832 bytes in 13 blocks are definitely lost in loss record 46 of 64
==26068==    at 0x483BE63: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==26068==    by 0x7A7609D: sco::OSQPModel::addEqCnt(sco::AffExpr const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (osqp_interface.cpp:57)
==26068==    by 0x7A12023: sco::ConvexObjective::addConstraintsToModel() (modeling.cpp:84)
==26068==    by 0x7A257F7: sco::BasicTrustRegionSQP::optimize() (optimizers.cpp:625)
==26068==    by 0x65C326C: tesseract_planning::TrajOptMotionPlanner::solve(tesseract_planning::PlannerRequest const&, tesseract_planning::PlannerResponse&, bool) const (trajopt_motion_planner.cpp:158)
==26068==    by 0x4C35336: tesseract_planning::MotionPlannerTaskGenerator::conditionalProcess(tesseract_planning::TaskInput, unsigned long) const (motion_planner_task_generator.cpp:160)
==26068==    by 0x4BA711D: tesseract_planning::TaskGenerator::assignConditionalTask(tesseract_planning::TaskInput, tf::Task&)::{lambda()#1}::operator()() const (task_generator.cpp:63)
==26068==    by 0x4BA84E9: std::_Function_handler<int (), tesseract_planning::TaskGenerator::assignConditionalTask(tesseract_planning::TaskInput, tf::Task&)::{lambda()#1}>::_M_invoke(std::_Any_data const&) (std_function.h:285)
==26068==    by 0x4BBA29D: std::function<int ()>::operator()() const (std_function.h:688)
==26068==    by 0x4BB5C9E: tf::Executor::_invoke_condition_work(tf::Executor::Worker&, tf::Node*) (executor.hpp:969)
==26068==    by 0x4BB51F1: tf::Executor::_invoke(tf::Executor::Worker&, tf::Node*) (executor.hpp:781)
==26068==    by 0x4BB45C6: tf::Executor::_exploit_task(tf::Executor::Worker&, tf::Node*&) (executor.hpp:533)

...

==26068== 10,192 bytes in 182 blocks are definitely lost in loss record 64 of 64
==26068==    at 0x483BE63: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==26068==    by 0x7A75F6E: sco::OSQPModel::addVar(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (osqp_interface.cpp:49)
==26068==    by 0x79EA6F4: sco::Model::addVar(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, double, double) (solver_interface.cpp:103)
==26068==    by 0x7A13077: sco::OptProb::createVariables(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::vector<double, std::allocator<double> > const&, std::vector<double, std::allocator<double> > const&) (modeling.cpp:179)
==26068==    by 0x768DCA0: trajopt::TrajOptProb::TrajOptProb(int, trajopt::ProblemConstructionInfo const&) (problem_description.cpp:569)
==26068==    by 0x768C0A7: trajopt::ConstructProblem(trajopt::ProblemConstructionInfo const&) (problem_description.cpp:445)
==26068==    by 0x65C30B5: tesseract_planning::TrajOptMotionPlanner::solve(tesseract_planning::PlannerRequest const&, tesseract_planning::PlannerResponse&, bool) const (trajopt_motion_planner.cpp:137)

==26068== LEAK SUMMARY:
==26068==    definitely lost: 12,928 bytes in 228 blocks
==26068==    indirectly lost: 0 bytes in 0 blocks
==26068==      possibly lost: 0 bytes in 0 blocks
==26068==    still reachable: 57,832 bytes in 817 blocks
==26068==         suppressed: 0 bytes in 0 blocks
mpowelson commented 3 years ago

I think I found it. I'll submit a PR shortly

==36055== LEAK SUMMARY:
==36055==    definitely lost: 0 bytes in 0 blocks
==36055==    indirectly lost: 0 bytes in 0 blocks
==36055==      possibly lost: 0 bytes in 0 blocks
==36055==    still reachable: 57,832 bytes in 817 blocks
==36055==         suppressed: 0 bytes in 0 blocks
Levi-Armstrong commented 3 years ago

This gives a good explanation of valgrind memory leak.

https://stackoverflow.com/questions/3840582/still-reachable-leak-detected-by-valgrind