MRPT / mrpt

:zap: The Mobile Robot Programming Toolkit (MRPT)
https://docs.mrpt.org/reference/latest/
BSD 3-Clause "New" or "Revised" License
1.95k stars 632 forks source link

PlannerSimple2D.computePath segfaults on armhf #290

Closed bnjff closed 8 years ago

bnjff commented 8 years ago

Path planning code segfaults while using MRPT on armhf architecture (jetson TX1). MRPT installed from ppa:joseluisblancoc/mrpt.

PlannerSimple2D pathPlanning
pathPlanning.computePath(gridmap, origin, target, thePath, notFound, -1);

results in the following error:

Program received signal SIGSEGV, Segmentation fault. 0xf71df994 in mrpt::nav::PlannerSimple2D::computePath(mrpt::maps::COccupancyGridMap2D const&, mrpt::poses::CPose2D const&, mrpt::poses::CPose2D const&, std::deque<mrpt::math::TPoint2D, std::allocator >&, bool&, float) const () from /usr/lib/arm-linux-gnueabihf/libmrpt-nav.so.1.5 (gdb) bt

0 0xf71df994 in mrpt::nav::PlannerSimple2D::computePath(mrpt::maps::COccupancyGridMap2D const&, mrpt::poses::CPose2D const&, mrpt::poses::CPose2D const&, std::deque<mrpt::math::TPoint2D, std::allocator >&, bool&, float) const () from /usr/lib/arm-linux-gnueabihf/libmrpt-nav.so.1.5

1 0x00000000 in ?? ()

Same code runs on amd64 laptop.

jlblancoc commented 8 years ago

Thanks for the report!

Could you please install the valgrind package and run the program with it on armhf? Something like:

valgrind --log-file=LOG.txt <YOUR_EXECUTABLE_NAME>

Hopefully the logfile will tell us something more...

bnjff commented 8 years ago

Thanks for your response! Here's the log:

==12372== Memcheck, a memory error detector ==12372== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. ==12372== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info ==12372== Command: ../../devel/lib/gohbot_control/simple_planner ==12372== Parent PID: 12310 ==12372== ==12372== Invalid read of size 2 ==12372== at 0x4E54A24: mrpt::nav::PlannerSimple2D::computePath(mrpt::maps::COccupancyGridMap2D const&, mrpt::poses::CPose2D const&, mrpt::poses::CPose2D const&, std::deque<mrpt::math::TPoint2D, std::allocator >&, bool&, float) const (in /usr/lib/arm-linux-gnueabihf/libmrpt-nav.so.1.5.0) ==12372== Address 0xb65a2aa is 6 bytes before a block of size 16 free'd ==12372== at 0x4830598: operator delete (vg_replace_malloc.c:542) ==12372== by 0x4B213: void boost::checked_arraydelete(unsigned char) (in /home/ubuntu/gohbot_ws/devel/lib/gohbot_control/simple_planner) ==12372== ==12372== Invalid read of size 2 ==12372== at 0x4E54A54: mrpt::nav::PlannerSimple2D::computePath(mrpt::maps::COccupancyGridMap2D const&, mrpt::poses::CPose2D const&, mrpt::poses::CPose2D const&, std::deque<mrpt::math::TPoint2D, std::allocator >&, bool&, float) const (in /usr/lib/arm-linux-gnueabihf/libmrpt-nav.so.1.5.0) ==12372== Address 0xb65a2a8 is 8 bytes before a block of size 16 free'd ==12372== at 0x4830598: operator delete (vg_replace_malloc.c:542) ==12372== by 0x4B213: void boost::checked_arraydelete(unsigned char) (in /home/ubuntu/gohbot_ws/devel/lib/gohbot_control/simple_planner) ==12372== ==12372== Invalid read of size 2 ==12372== at 0x4E54A9E: mrpt::nav::PlannerSimple2D::computePath(mrpt::maps::COccupancyGridMap2D const&, mrpt::poses::CPose2D const&, mrpt::poses::CPose2D const&, std::deque<mrpt::math::TPoint2D, std::allocator >&, bool&, float) const (in /usr/lib/arm-linux-gnueabihf/libmrpt-nav.so.1.5.0) ==12372== Address 0xb65a2ac is 4 bytes before a block of size 16 free'd ==12372== at 0x4830598: operator delete (vg_replace_malloc.c:542) ==12372== by 0x4B213: void boost::checked_arraydelete(unsigned char) (in /home/ubuntu/gohbot_ws/devel/lib/gohbot_control/simple_planner) ==12372== ==12372== Invalid read of size 2 ==12372== at 0x4E54994: mrpt::nav::PlannerSimple2D::computePath(mrpt::maps::COccupancyGridMap2D const&, mrpt::poses::CPose2D const&, mrpt::poses::CPose2D const&, std::deque<mrpt::math::TPoint2D, std::allocator >&, bool&, float) const (in /usr/lib/arm-linux-gnueabihf/libmrpt-nav.so.1.5.0) ==12372== Address 0xb65a2aa is 6 bytes before a block of size 16 free'd ==12372== at 0x4830598: operator delete (vg_replace_malloc.c:542) ==12372== by 0x4B213: void boost::checked_arraydelete(unsigned char) (in /home/ubuntu/gohbot_ws/devel/lib/gohbot_control/simple_planner) ==12372== ==12372== Invalid read of size 2 ==12372== at 0x4E553D6: mrpt::nav::PlannerSimple2D::computePath(mrpt::maps::COccupancyGridMap2D const&, mrpt::poses::CPose2D const&, mrpt::poses::CPose2D const&, std::deque<mrpt::math::TPoint2D, std::allocator >&, bool&, float) const (in /usr/lib/arm-linux-gnueabihf/libmrpt-nav.so.1.5.0) ==12372== Address 0xb68d7c8 is 207,080 bytes inside an unallocated block of size 690,456 in arena "client" ==12372== ==12372== Invalid read of size 2 ==12372== at 0x4E55406: mrpt::nav::PlannerSimple2D::computePath(mrpt::maps::COccupancyGridMap2D const&, mrpt::poses::CPose2D const&, mrpt::poses::CPose2D const&, std::deque<mrpt::math::TPoint2D, std::allocator >&, bool&, float) const (in /usr/lib/arm-linux-gnueabihf/libmrpt-nav.so.1.5.0) ==12372== Address 0xb68d7c6 is 207,078 bytes inside an unallocated block of size 690,456 in arena "client" ==12372== ==12372== Invalid read of size 2 ==12372== at 0x4E55428: mrpt::nav::PlannerSimple2D::computePath(mrpt::maps::COccupancyGridMap2D const&, mrpt::poses::CPose2D const&, mrpt::poses::CPose2D const&, std::deque<mrpt::math::TPoint2D, std::allocator >&, bool&, float) const (in /usr/lib/arm-linux-gnueabihf/libmrpt-nav.so.1.5.0) ==12372== Address 0xb68d7ca is 207,082 bytes inside an unallocated block of size 690,456 in arena "client" ==12372== ==12372== Invalid read of size 2 ==12372== at 0x4E55452: mrpt::nav::PlannerSimple2D::computePath(mrpt::maps::COccupancyGridMap2D const&, mrpt::poses::CPose2D const&, mrpt::poses::CPose2D const&, std::deque<mrpt::math::TPoint2D, std::allocator >&, bool&, float) const (in /usr/lib/arm-linux-gnueabihf/libmrpt-nav.so.1.5.0) ==12372== Address 0xb68d420 is 206,144 bytes inside an unallocated block of size 690,456 in arena "client" ==12372== ==12372== Invalid read of size 2 ==12372== at 0x4E55476: mrpt::nav::PlannerSimple2D::computePath(mrpt::maps::COccupancyGridMap2D const&, mrpt::poses::CPose2D const&, mrpt::poses::CPose2D const&, std::deque<mrpt::math::TPoint2D, std::allocator >&, bool&, float) const (in /usr/lib/arm-linux-gnueabihf/libmrpt-nav.so.1.5.0) ==12372== Address 0xb68db70 is 208,016 bytes inside an unallocated block of size 690,456 in arena "client" ==12372== ==12372== Invalid read of size 2 ==12372== at 0x4E55498: mrpt::nav::PlannerSimple2D::computePath(mrpt::maps::COccupancyGridMap2D const&, mrpt::poses::CPose2D const&, mrpt::poses::CPose2D const&, std::deque<mrpt::math::TPoint2D, std::allocator >&, bool&, float) const (in /usr/lib/arm-linux-gnueabihf/libmrpt-nav.so.1.5.0) ==12372== Address 0xb68d41e is 206,142 bytes inside an unallocated block of size 690,456 in arena "client" ==12372== ==12372== Invalid read of size 2 ==12372== at 0x4E5549C: mrpt::nav::PlannerSimple2D::computePath(mrpt::maps::COccupancyGridMap2D const&, mrpt::poses::CPose2D const&, mrpt::poses::CPose2D const&, std::deque<mrpt::math::TPoint2D, std::allocator >&, bool&, float) const (in /usr/lib/arm-linux-gnueabihf/libmrpt-nav.so.1.5.0) ==12372== Address 0xb68d422 is 206,146 bytes inside an unallocated block of size 690,456 in arena "client" ==12372== ==12372== Invalid read of size 2 ==12372== at 0x4E554D4: mrpt::nav::PlannerSimple2D::computePath(mrpt::maps::COccupancyGridMap2D const&, mrpt::poses::CPose2D const&, mrpt::poses::CPose2D const&, std::deque<mrpt::math::TPoint2D, std::allocator >&, bool&, float) const (in /usr/lib/arm-linux-gnueabihf/libmrpt-nav.so.1.5.0) ==12372== Address 0xb68db6e is 208,014 bytes inside an unallocated block of size 690,456 in arena "client" ==12372== ==12372== Invalid read of size 2 ==12372== at 0x4E554F4: mrpt::nav::PlannerSimple2D::computePath(mrpt::maps::COccupancyGridMap2D const&, mrpt::poses::CPose2D const&, mrpt::poses::CPose2D const&, std::deque<mrpt::math::TPoint2D, std::allocator >&, bool&, float) const (in /usr/lib/arm-linux-gnueabihf/libmrpt-nav.so.1.5.0) ==12372== Address 0xb68db72 is 208,018 bytes inside an unallocated block of size 690,456 in arena "client" ==12372== ==12372== Conditional jump or move depends on uninitialised value(s) ==12372== at 0x4E553DC: mrpt::nav::PlannerSimple2D::computePath(mrpt::maps::COccupancyGridMap2D const&, mrpt::poses::CPose2D const&, mrpt::poses::CPose2D const&, std::deque<mrpt::math::TPoint2D, std::allocator >&, bool&, float) const (in /usr/lib/arm-linux-gnueabihf/libmrpt-nav.so.1.5.0) ==12372== ==12372== Conditional jump or move depends on uninitialised value(s) ==12372== at 0x4E55410: mrpt::nav::PlannerSimple2D::computePath(mrpt::maps::COccupancyGridMap2D const&, mrpt::poses::CPose2D const&, mrpt::poses::CPose2D const&, std::deque<mrpt::math::TPoint2D, std::allocator >&, bool&, float) const (in /usr/lib/arm-linux-gnueabihf/libmrpt-nav.so.1.5.0) ==12372== ==12372== Conditional jump or move depends on uninitialised value(s) ==12372== at 0x4E55432: mrpt::nav::PlannerSimple2D::computePath(mrpt::maps::COccupancyGridMap2D const&, mrpt::poses::CPose2D const&, mrpt::poses::CPose2D const&, std::deque<mrpt::math::TPoint2D, std::allocator >&, bool&, float) const (in /usr/lib/arm-linux-gnueabihf/libmrpt-nav.so.1.5.0) ==12372== ==12372== Conditional jump or move depends on uninitialised value(s) ==12372== at 0x4E5545C: mrpt::nav::PlannerSimple2D::computePath(mrpt::maps::COccupancyGridMap2D const&, mrpt::poses::CPose2D const&, mrpt::poses::CPose2D const&, std::deque<mrpt::math::TPoint2D, std::allocator >&, bool&, float) const (in /usr/lib/arm-linux-gnueabihf/libmrpt-nav.so.1.5.0) ==12372== ==12372== Conditional jump or move depends on uninitialised value(s) ==12372== at 0x4E55480: mrpt::nav::PlannerSimple2D::computePath(mrpt::maps::COccupancyGridMap2D const&, mrpt::poses::CPose2D const&, mrpt::poses::CPose2D const&, std::deque<mrpt::math::TPoint2D, std::allocator >&, bool&, float) const (in /usr/lib/arm-linux-gnueabihf/libmrpt-nav.so.1.5.0) ==12372== ==12372== Conditional jump or move depends on uninitialised value(s) ==12372== at 0x4E554AC: mrpt::nav::PlannerSimple2D::computePath(mrpt::maps::COccupancyGridMap2D const&, mrpt::poses::CPose2D const&, mrpt::poses::CPose2D const&, std::deque<mrpt::math::TPoint2D, std::allocator >&, bool&, float) const (in /usr/lib/arm-linux-gnueabihf/libmrpt-nav.so.1.5.0) ==12372== ==12372== Conditional jump or move depends on uninitialised value(s) ==12372== at 0x4E554C8: mrpt::nav::PlannerSimple2D::computePath(mrpt::maps::COccupancyGridMap2D const&, mrpt::poses::CPose2D const&, mrpt::poses::CPose2D const&, std::deque<mrpt::math::TPoint2D, std::allocator >&, bool&, float) const (in /usr/lib/arm-linux-gnueabihf/libmrpt-nav.so.1.5.0) ==12372== ==12372== Conditional jump or move depends on uninitialised value(s) ==12372== at 0x4E554DE: mrpt::nav::PlannerSimple2D::computePath(mrpt::maps::COccupancyGridMap2D const&, mrpt::poses::CPose2D const&, mrpt::poses::CPose2D const&, std::deque<mrpt::math::TPoint2D, std::allocator >&, bool&, float) const (in /usr/lib/arm-linux-gnueabihf/libmrpt-nav.so.1.5.0) ==12372== ==12372== Conditional jump or move depends on uninitialised value(s) ==12372== at 0x4E554FE: mrpt::nav::PlannerSimple2D::computePath(mrpt::maps::COccupancyGridMap2D const&, mrpt::poses::CPose2D const&, mrpt::poses::CPose2D const&, std::deque<mrpt::math::TPoint2D, std::allocator >&, bool&, float) const (in /usr/lib/arm-linux-gnueabihf/libmrpt-nav.so.1.5.0) ==12372== ==12372== ==12372== Process terminating with default action of signal 11 (SIGSEGV) ==12372== Access not within mapped region at address 0xCD8E8D2 ==12372== at 0x4E553D6: mrpt::nav::PlannerSimple2D::computePath(mrpt::maps::COccupancyGridMap2D const&, mrpt::poses::CPose2D const&, mrpt::poses::CPose2D const&, std::deque<mrpt::math::TPoint2D, std::allocator >&, bool&, float) const (in /usr/lib/arm-linux-gnueabihf/libmrpt-nav.so.1.5.0) ==12372== If you believe this happened as a result of a stack ==12372== overflow in your program's main thread (unlikely but ==12372== possible), you can try to increase the size of the ==12372== main thread stack using the --main-stacksize= flag. ==12372== The main thread stack size used in this run was 8388608. ==12372== ==12372== HEAP SUMMARY: ==12372== in use at exit: 4,269,224 bytes in 13,460 blocks ==12372== total heap usage: 32,897 allocs, 19,437 frees, 757,601,615 bytes allocated ==12372== ==12372== LEAK SUMMARY: ==12372== definitely lost: 0 bytes in 0 blocks ==12372== indirectly lost: 0 bytes in 0 blocks ==12372== possibly lost: 605,339 bytes in 10,061 blocks ==12372== still reachable: 3,663,885 bytes in 3,399 blocks ==12372== suppressed: 0 bytes in 0 blocks ==12372== Rerun with --leak-check=full to see details of leaked memory ==12372== ==12372== For counts of detected and suppressed errors, rerun with: -v ==12372== Use --track-origins=yes to see where uninitialised values come from ==12372== ERROR SUMMARY: 959 errors from 22 contexts (suppressed: 25 from 14)

jlblancoc commented 8 years ago

I see something suspicious regarding boost which should probably come from some container in your test program, maybe??

Could you please provide a minimal small program (.cpp + CMakeLists.txt+map files+...) which leads to this crash so I can further investigate it?

bnjff commented 8 years ago

I think the issue is solved. The problem was that char type is translated to signed char on most machines, however Jetson TX1 translates it to unsigned char. As a result gradient directions dx, dy, initialized as 0, typically become 255 (dx=0-1=255), and then x+=dx keeps incrementing until segfault. https://github.com/bnjff/mrpt/commit/001cbe26c81ee4394159f34958ffd8624e2a8348

jlblancoc commented 8 years ago

Thanks a lot for the research! I just merged your changes :+1:

jolting commented 8 years ago

Nice. Here's a good article on this: http://blog.cdleary.com/2012/11/arm-chars-are-unsigned-by-default/

In summary, ARM historically didn't have a single instruction load and sign extend, so they made all their chars unsigned. Now it shouldn't affect performance, but you can use -fsigned-char/-funsigned-char to set this behavior globally.

The header file stdint.h or cstdint was not supported by visual studio since they never claimed to support C99. Fixed width integer types have been available on nearly every other platform, since both clang and gcc support c99. I believe c++11 now mandates the fixed width integer types that were part of C99, so visual studio I believe supports it with c++11. int8_t would be the correct signed type on all platforms. Might want to add that to the 2.0 effort.

http://en.cppreference.com/w/cpp/types/integer

jlblancoc commented 8 years ago

Good point!

For the records: msvc 2015 finally (!) includes that header... was about time.

I don't have problems with adding C++11 features to cpp files in mrpt now, a long as they are supported by msvc 2012 and it's only in the cpp files, not in public headers exposed to users ;-)