内存问题检测

内存检测方式

gcc/g++ 内存检测方式如下,添加一些编译标签:

  • -fsanitize=leak   检测内存泄漏。例如添加标签:-fsanitize=leak -g -O0
  • -fsanitize=address  检测内存越界。例如添加标签:-fsanitize=address -g -O2,优化级别开启 O2 也可以检测到
  • -fsanitize=undefined  检测未定义的行为,例如:使用未初始化的变量、除 0、空指针解引用等

编译完,代码跑起来后,回放录包,录包跑完后,可以按 ctrl c,会输出内存检测结果(对应的调用栈)到标准出错

【注意:这种检测方式是运行时检测,如果有些代码没有运行到,这些代码就检测不到,需要链接 asan 库,或者 export LD_PRELOAD=/lib/aarch64-linux-gnu/libasan.so.5:${LD_PRELOAD}】

使用这种方式,实际上已经帮助系统组解决了一些中间件的 coredump 问题、planning 的内存泄漏问题、perception 的内存越界问题,比较好用

其中,协助 rs_perception 杨代玉解决内存问题时,【内存越界|内存泄漏检测方法-CSDN博客】文档很好:

内存问题,出现过的 case

可能导致内存问题的原因(后续协助算法做内存问题检测时,新的 case 可以继续在下面加):

1. 释放了没有分配的内存,报错为:AddressSanitizer: attempting free on address which was not malloc()-ed

2. new 和 delete 不匹配,报错为:AddressSanitizer: alloc-dealloc-mismatch (operator new [] vs operator delete)

new 分配一个数组,应该用 delete[] 去释放,而不是用 delete 释放

例如:auto output = std::shared_ptr(new float[num_obj * 9]);
应该改为:
auto output = std::shared_ptr(new float[num_obj * 9], [](float* p) { delete[] p; });

3. 内存越界,报错为:AddressSanitizer: heap-buffer-overflow on address 或者 AddressSanitizer: stack-buffer-overflow on address

例如:使用 for(int i = 1; i < 4; ++i) 去遍历修改数组中的对象,数组长度为 3 的话,会存在内存越界问题

4. 内存泄漏,报错为:LeakSanitizer: detected memory leaks

  • 忘记释放内存
  • 存在循环引用问题。例如伪代码如下:

    struct A {

        std::shared_ptr<struct A> sa;

        std::shared_ptr<struct A> sb;

    }

    struct B {

        std::shared_ptr<struct A> sa;

        std::shared_ptr<struct B> sb;

    }

    int main () {

        shared_ptr<A> pa(new A());

        pa->sa = pa;  // 案例一:循环引用,自己的成员指向自己,出现循环引用。释放时,无法释放 pa

        shared_ptr<B> pb(new B());

        pa->sb = pb;  // 案例二:pa->sb 指向 pb,pb->sa 指向 pa,出现循环引用。释放时,会导致 pa 和 pb 都无法释放

        pb->sa = pa;

        return 0;

    }

5. 第三方库内存 bug

如下 pcl 库的 bug,升级到 pcl1.9 可解决

==9889==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x007f6ab4eeb8 at pc 0x007f9b129370 bp 0x007c3bdf3940 sp 0x007c3bdf3960

READ of size 8 at 0x007f6ab4eeb8 thread T36

==9889==AddressSanitizer: while reporting a bug found another one. Ignoring.

    #0 0x7f9b12936f in Eigen::internal::handmade_aligned_free(void*) /usr/include/eigen3/Eigen/src/Core/util/Memory.h:118

    #1 0x7f9b12936f in Eigen::internal::aligned_free(void*) /usr/include/eigen3/Eigen/src/Core/util/Memory.h:206

    #2 0x7f9b12936f in void Eigen::internal::conditional_aligned_free<true>(void*) /usr/include/eigen3/Eigen/src/Core/util/Memory.h:259

    #3 0x7f9b12936f in void Eigen::internal::conditional_aligned_delete_auto<floattrue>(float*, unsigned long) /usr/include/eigen3/Eigen/src/Core/util/Memory.h:446

    #4 0x7f9b12936f in Eigen::DenseStorage<float, -1, -1, -10>::~DenseStorage() /usr/include/eigen3/Eigen/src/Core/DenseStorage.h:415

    #5 0x7f9b12936f in Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -10, -1, -1> >::~PlainObjectBase() /usr/include/eigen3/Eigen/src/Core/PlainObjectBase.h:98

    #6 0x7f9b12936f in Eigen::Matrix<float, -1, -10, -1, -1>::~Matrix() /usr/include/eigen3/Eigen/src/Core/Matrix.h:178

    #7 0x7f9b12936f in void Eigen::internal::call_assignment<Eigen::Matrix<float, -1, -10, -1, -1>, Eigen::CwiseBinaryOp<Eigen::internal::scalar_difference_op<floatfloat>, Eigen::Matrix<float, -1, -10, -1, -1const, Eigen::Product<Eigen::Product<Eigen::Matrix<float, -1, -10, -1, -1>, Eigen::Matrix<float, -1, -10, -1, -1>, 0>, Eigen::Matrix<float, -1, -10, -1, -1>, 0const>, Eigen::internal::assign_op<floatfloat> >(Eigen::Matrix<float, -1, -10, -1, -1>&, Eigen::CwiseBinaryOp<Eigen::internal::scalar_difference_op<floatfloat>, Eigen::Matrix<float, -1, -10, -1, -1const, Eigen::Product<Eigen::Product<Eigen::Matrix<float, -1, -10, -1, -1>, Eigen::Matrix<float, -1, -10, -1, -1>, 0>, Eigen::Matrix<float, -1, -10, -1, -1>, 0constconst&, Eigen::internal::assign_op<floatfloatconst&, Eigen::internal::enable_if<Eigen::internal::evaluator_assume_aliasing<Eigen::CwiseBinaryOp<Eigen::internal::scalar_difference_op<floatfloat>, Eigen::Matrix<float, -1, -10, -1, -1const, Eigen::Product<Eigen::Product<Eigen::Matrix<float, -1, -10, -1, -1>, Eigen::Matrix<float, -1, -10, -1, -1>, 0>, Eigen::Matrix<float, -1, -10, -1, -1>, 0const>, Eigen::internal::evaluator_traits<Eigen::CwiseBinaryOp<Eigen::internal::scalar_difference_op<floatfloat>, Eigen::Matrix<float, -1, -10, -1, -1const, Eigen::Product<Eigen::Product<Eigen::Matrix<float, -1, -10, -1, -1>, Eigen::Matrix<float, -1, -10, -1, -1>, 0>, Eigen::Matrix<float, -1, -10, -1, -1>, 0const> >::Shape>::value, void*>::type) /usr/include/eigen3/Eigen/src/Core/AssignEvaluator.h:840

    #8 0x7f9b12936f in void Eigen::internal::call_assignment<Eigen::Matrix<float, -1, -10, -1, -1>, Eigen::CwiseBinaryOp<Eigen::internal::scalar_difference_op<floatfloat>, Eigen::Matrix<float, -1, -10, -1, -1const, Eigen::Product<Eigen::Product<Eigen::Matrix<float, -1, -10, -1, -1>, Eigen::Matrix<float, -1, -10, -1, -1>, 0>, Eigen::Matrix<float, -1, -10, -1, -1>, 0const> >(Eigen::Matrix<float, -1, -10, -1, -1>&, Eigen::CwiseBinaryOp<Eigen::internal::scalar_difference_op<floatfloat>, Eigen::Matrix<float, -1, -10, -1, -1const, Eigen::Product<Eigen::Product<Eigen::Matrix<float, -1, -10, -1, -1>, Eigen::Matrix<float, -1, -10, -1, -1>, 0>, Eigen::Matrix<float, -1, -10, -1, -1>, 0constconst&) /usr/include/eigen3/Eigen/src/Core/AssignEvaluator.h:826

    #9 0x7f9b12936f in Eigen::Matrix<float, -1, -10, -1, -1>& Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -10, -1, -1> >::_set<Eigen::CwiseBinaryOp<Eigen::internal::scalar_difference_op<floatfloat>, Eigen::Matrix<float, -1, -10, -1, -1const, Eigen::Product<Eigen::Product<Eigen::Matrix<float, -1, -10, -1, -1>, Eigen::Matrix<float, -1, -10, -1, -1>, 0>, Eigen::Matrix<float, -1, -10, -1, -1>, 0const> >(Eigen::DenseBase<Eigen::CwiseBinaryOp<Eigen::internal::scalar_difference_op<floatfloat>, Eigen::Matrix<float, -1, -10, -1, -1const, Eigen::Product<Eigen::Product<Eigen::Matrix<float, -1, -10, -1, -1>, Eigen::Matrix<float, -1, -10, -1, -1>, 0>, Eigen::Matrix<float, -1, -10, -1, -1>, 0const> > const&) /usr/include/eigen3/Eigen/src/Core/PlainObjectBase.h:779

    #10 0x7f9b12936f in Eigen::Matrix<float, -1, -10, -1, -1>& Eigen::Matrix<float, -1, -10, -1, -1>::operator=<Eigen::CwiseBinaryOp<Eigen::internal::scalar_difference_op<floatfloat>, Eigen::Matrix<float, -1, -10, -1, -1const, Eigen::Product<Eigen::Product<Eigen::Matrix<float, -1, -10, -1, -1>, Eigen::Matrix<float, -1, -10, -1, -1>, 0>, Eigen::Matrix<float, -1, -10, -1, -1>, 0const> >(Eigen::DenseBase<Eigen::CwiseBinaryOp<Eigen::internal::scalar_difference_op<floatfloat>, Eigen::Matrix<float, -1, -10, -1, -1const, Eigen::Product<Eigen::Product<Eigen::Matrix<float, -1, -10, -1, -1>, Eigen::Matrix<float, -1, -10, -1, -1>, 0>, Eigen::Matrix<float, -1, -10, -1, -1>, 0const> > const&) /usr/include/eigen3/Eigen/src/Core/Matrix.h:225

    #11 0x7f9b12936f in robosense::KalmanFilter::update(Eigen::Matrix<float, -110, -11>&) /home/mogo/data/yangdaiyu/perception_ws/src/perception/lidar/robosense/modules/perception/lidar/tracking/src/filter/kalman_filter.cpp:137

6. coredump 文件,用 gdb 看到堆栈被踩坏,报错为:previous frame identical to this frame(corrupt stack?)

此时通过 gdb 看到的堆栈不一定是踩坏内存的堆栈,

栈是从高到低分配的,入栈时,sp 指针向低地址移动。假如在栈 #10 分配一个 int arr[100]。如果内存越界,例如执行了 arr[10000] = 123, 此时,10000 是高地址位,是有可能把栈踩坏的。踩坏时,不一定导致 coredump,程序继续运行,直到运行时报错,此时再看 coredump 文件,堆栈已经不是把内存踩坏时的堆栈了。

解问题方法:

    使用-fsanitize=address ,然后回放录包检测

    可以用反汇编看看,是不是把一些全局变量踩坏了,例如 futex

内存越界 demo

cat main.cpp

#include <stdio.h>

#include <string.h>

void fun(int n)

{

    printf("The %d step begin.\n", n);

    int a[10];

    for (int i = 0; i< n; i++) {

        a[i] = i;

    }

    if (n < 20) {

        fun(n +1);

    }

    printf("The %d step end\n", n);

}

int main(void)

{

    fun(8);

    return 0;

}

$ g++ main.cpp -o main -fsanitize=address -g -O2

$ ./main

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/387640.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

02 I/O多路复用---进程的聊天

服务器同时和很多客户端连在一起 管道的read&#xff0c;总是能读出来

前后端分离开发遵循接口规范-YAPI

目前&#xff0c;网站主流开发方式是前后端分离。因此前后端必须遵循一套统一的规范&#xff0c;才能保证前后端进行正常的数据&#xff08;JSON数据格式&#xff09;请求、影响&#xff0c;这套规范即是 YAPI. 产品经理撰写原型&#xff1b; 前端或后端撰写接口文档。 YAPI…

Android高级interview

一、Android基础知识 1、四大组件、六大布局、五大存储 四大组件&#xff1a; activity、service、content provider、broadcast六大布局&#xff08;现在是 7 大了&#xff09;: 线性布局&#xff08;LinearLayout&#xff09;相对布局&#xff08;RelativeLayout&#xf…

替换后端国外身份目录服务,宁盾身份域管接管FileNet助力国产化升级

IBM FileNet 是一款优秀的企业内容管理解决方案&#xff0c;为客户提供了领先的文档管理和流程管理集成环境&#xff0c;被大量企业所采用。FileNet 需要使用企业级的目录服务器&#xff08;LDAP&#xff09;作为其用户管理系统&#xff0c;满足其认证和授权的需求。对于 LDAP …

成为git砖家(4): git status 命令简介

1. untracked 和 tracked 状态 Remember that each file in your working directory can be in one of two states: tracked or untracked. Tracked files are files that were in the last snapshot, as well as any newly staged files; they can be unmodified, modified, o…

zabbix使用脚本自定义监控项

1. 在zabbix_agent的配置文件中配置自定义key和脚本位置 vim /etc/zabbix/zabbix_agentd.confUserParametermq_check_log,/etc/zabbix/zabbix_agentd.d/mqlog.shmq_check_log&#xff1a;是这个自定义参数的名称。在Zabbix的监控项&#xff08;item&#xff09;配置中&#xf…

点菜吧——随便点 C#生成套餐

前言 一到食堂发现有多种选择&#xff0c;但是有一个固定的套路&#xff0c;只能是一个荤&#xff0c;二个小荤&#xff0c;菜品数量也不少&#xff0c;任君选择&#xff0c;如果是一个选择困难症&#xff0c;就有点烦了&#xff0c;所以出品这个自动生成套餐软件。各位老板可…

代码随想录算法训练营Day 63| 图论 part03 | 417.太平洋大西洋水流问题、827.最大人工岛、127. 单词接龙

代码随想录算法训练营Day 63| 图论 part03 | 417.太平洋大西洋水流问题、827.最大人工岛、127. 单词接龙 文章目录 代码随想录算法训练营Day 63| 图论 part03 | 417.太平洋大西洋水流问题、827.最大人工岛、127. 单词接龙17.太平洋大西洋水流问题一、DFS二、BFS三、本题总结 82…

在手机查看笔记本电脑上的便签 笔记本电脑和手机共享便签方法

在这个信息时代&#xff0c;笔记本电脑已成为我们工作和学习中不可或缺的工具。我经常在笔记本上记录各种便签&#xff0c;无论是工作中的待办事项&#xff0c;还是生活中的小提醒&#xff0c;都依赖于这些小小的便签。它们轻便、灵活&#xff0c;可以随时随地提醒我接下来要做…

TongHttpServer 简介

1. 概述 随着网络技术的飞速发展,高并发大用户场景越来越普遍,单一应用服务节点已经不能满足并发需求,为了提高整个系统可靠性,扩展性,吞吐率,通常将多个应用服务器通过硬负载/软负载组成集群,负载均衡器根据不同负载算法将请求分发到各个应用服务器节点。 Tong…

花几千上万学习Java,真没必要!(三十六)

1、File类&#xff1a; 测试代码1&#xff1a; package filetest.com; import java.io.File; import java.io.IOException; public class FileOperations { public static void main(String[] args) { // 创建新文件File file new File("example.txt"); tr…

Prometheus+Grafana+Alertmanager监控告警

PrometheusGrafanaAlertmanager告警 Alertmanager开源地址&#xff1a;github.com/prometheus Prometheus是一款基于时序数据库的开源监控告警系统&#xff0c;它是SoundCloud公司开源的&#xff0c;SoundCloud的服务架构是微服务架构&#xff0c;他们开发了很多微服务&#xf…

TCP为什么需要四次挥手?

tcp为什么需要四次挥手&#xff1f; 答案有两个&#xff1a; 1.将发送fin包的权限交给被动断开方的应用层去处理&#xff0c;也就是让程序员处理 2.接第一个答案&#xff0c;应用层有了发送fin的权限&#xff0c;可以在发送fin前继续向对端发送消息 为了搞清楚这个问题&…

前端开发知识-vue

大括号里边放键值对&#xff0c;即是一个对象。 一、vue可以简化前端javascript的操作。 主要特点是可以实现视图、数据的双向绑定。 使用vue主要分为三个步骤&#xff1a; 1.javascript中引入vue.js 可以src中可以是vue的网址&#xff0c;也可以是本地下载。 2.在javasc…

网络爬虫必备工具:代理IP科普指南

文章目录 1. 网络爬虫简介1.1 什么是网络爬虫&#xff1f;1.2 网络爬虫的应用领域1.3 网络爬虫面临的主要挑战 2. 代理IP&#xff1a;爬虫的得力助手2.1 代理IP的定义和工作原理2.2 爬虫使用代理IP的必要性 3. 代理IP的类型及其在爬虫中的应用3.1 动态住宅代理3.2 动态数据中心…

数据挖掘-数据预处理

来自&#x1f96c;&#x1f436;程序员 Truraly | 田园 的博客&#xff0c;最新文章首发于&#xff1a;田园幻想乡 | 原文链接 | github &#xff08;欢迎关注&#xff09; 文章目录 3.3.1 数据的中心趋势平均数和加权平均数众数&#xff0c;中位数和均值描述数据的离散程度 &a…

【MySQL】用户管理连接池原理{数据库权限/连接池/mysql访问逻辑}

文章目录 1.普通用户的引入用户创建用户删除用户修改用户密码 2.数据库的权限给用户授权回收权限实操过程 3.简略介绍mysql连接池3.一个用户注册/登录/使用网页版mysql逻辑 1.普通用户的引入 用户 MySQL中的用户&#xff0c;都存储在系统数据库mysql的user表中 mysql> use…

uniapp微信小程序本地和真机调试文件图片上传成功但体验版不成功

文章目录 导文是因为要添加服务器域名&#xff01; 导文 uniapp微信小程序本地和真机调试文件图片上传成功但体验版不成功 uniapp微信小程序体验版上传图片不成功 微信小程序本地和真机调试文件图片上传成功但体验版不成功 是因为要添加服务器域名&#xff01; 先看一下 你小程…

解决jenkins配置extendreport不展示样式

下载插件&#xff1a;Groovy 、 HTML Publisher plugin 配置&#xff1a; 1&#xff09;Post Steps &#xff1a; 增加 Execute system Groovy script &#xff0c; 内容&#xff1a; System.setProperty("hudson.model.DirectoryBrowserSupport.CSP", "&qu…