内存泄漏检测可在CMakeLists.txt 文件中,添加 -fsanitize=leak
set(CMAKE_CXX_FLAGS "-fsanitize=leak -std=c++11 -g -Wall -Wno-unused-result -DROS ${CMAKE_CXX_FLAGS}")
g++ 加上 -fsanitize=leak 选项后,能打印内存泄漏时的堆栈。【进程运行结束或用 SIGINT 杀掉后,会打印内存泄漏的堆栈信息到标准出错】
内存错误操作可在CMakeLists.txt里面加上如下编译选项
set(CMAKE_CXX_FLAGS "-fsanitize=address -fno-omit-frame-pointer ${CMAKE_CXX_FLAGS}" )
当然,上述编译选项可以输出leak信息
内存错误操作:-fsanitize=address
多线程竞争:-fsanitize=thread
内存泄漏:-fsanitize=leak
未定义操作:-fsanitize=undefined(如:除0、空指针解引用、枚举值超范围、使用未初始化的变量值等)
#告诉address检测到异常不退出进程
set(ENV{ASAN_OPTIONS} "halt_on_error=0")
运行时可能会出现以下内存问题
对输出的ERROR重定向报错日志: roslaunch perception_lidar.launch 2> /home/mogo/data/yangdaiyu/address.log
1、AddressSanitizer: stack-use-after-scope on address
2、AddressSanitizer: attempting free on address which was not malloc()-ed
- /data/autocar/yangdaiyu/perception_ws/src/perception/lidar/robosense/modules/perception/lidar/ai_detection/src/pointpillars/pointpillars_ai_detection.cpp
msg_ptr->scan_ptr.reset(new PointCloud)
改:msg_ptr->resetMsg();
3、AddressSanitizer: alloc-dealloc-mismatch (operator new [] vs operator delete)
-
/data/autocar/yangdaiyu/perception_ws/src/perception/lidar/robosense/modules/perception/lidar/ai_detection/src/pointpillars/postprocess_cuda.cu
auto output = std::shared_ptr(new float[num_obj * 9]);
改:
auto output = std::shared_ptr(new float[num_obj * 9], [](float* p) { delete[] p; });
-
/data/autocar/yangdaiyu/perception_ws/src/perception/lidar/robosense/modules/perception/lidar/util/segmentor/src/rs_segmentor.cpp
seg_scan_x_mat.reset(new int[grid_size]);
seg_scan_y_mat.reset(new int[grid_size]);
智能指针对new的空间,若不指定释放方式,默认采用delete去释放,对于new数组空间无法全部释放,因此需要指定释放方式,如下:seg_scan_x_mat.reset(new int[grid_size], [](int* p) { delete[] p; });
seg_scan_y_mat.reset(new int[grid_size], [](int* p) { delete[] p; });
seed_mat.reset(new int[grid_size], [](int* p) { delete[] p; });
bin_mat.reset(new int[grid_size], [](int* p) { delete[] p; });
label_mat.reset(new int[grid_size], [](int* p) { delete[] p; });
-
perception/lidar/robosense/modules/common/src/basic_type/rotate_box.cpp:198 std::shared_ptr distPt;
distPt.reset(new double[N * N], [](int* p) { delete[] p;});
std::shared_ptr ptDistRemap;
ptDistRemap.reset(new int[N], [](int* p) { delete[] p;});
4、AddressSanitizer: heap-buffer-overflow on address 堆缓冲区溢出
-
size越界保护
if(track_object->track_type != ObjectType::UNKNOW) //加上类型判断,AI的polygon是4个点,但RB目标可能只有3个点,会超出界限{
for(int i = 1; i < 4; ++i){
if(track_object->object->polygons[i].norm() < track_object->object->polygons[index_corner_cur].norm()){
index_corner_cur = i;
index_corner_last = i;
}
}
}
-
Eigen::internal::handmade_aligned_free(void*)
在CMakeLists.txt里面加上add_definitions(-DPCL_NO_PRECOMPILE=ON)可以通过
此问题时PCL里的bug,升级PCL版本也可以解
5、LeakSanitizer: detected memory leaks
-
perception/lidar/robosense/modules/perception/infer/src/rs_trt_infer.cpp:156
#0 0x7fb54b343b in operator new(unsigned long) (/usr/lib/aarch64-linux-gnu/libasan.so.4+0xd243b)
#1 0x7f9ef34143 (/usr/lib/aarch64-linux-gnu/libnvinfer.so.7+0x4e7143)
#2 0x7f9f01dc77 in nvinfer1::rt::SafeEngine::deserializeCoreEngine(nvinfer1::rt::CoreReadArchive&, std::vector<nvinfer1::rt::EngineLayerAttribute, std::allocatornvinfer1::rt::EngineLayerAttribute >&) (/usr/lib/aarch64-linux-gnu/libnvinfer.so.7+0x5d0c77)
#3 0x7f9ed9f3b7 in nvinfer1::rt::Engine::deserialize(void const*, unsigned long, nvinfer1::IGpuAllocator&, nvinfer1::IPluginFactory*) (/usr/lib/aarch64-linux-gnu/libnvinfer.so.7+0x3523b7)
#4 0x7f9eda7f53 in nvinfer1::Runtime::deserializeCudaEngine(void const*, unsigned long, nvinfer1::IPluginFactory*) (/usr/lib/aarch64-linux-gnu/libnvinfer.so.7+0x35af53)
infer->deserializeCudaEngine(cahce_engine.c_str(), cahce_engine.size(), nullptr);