valgrind,memcheck的使用

一,valgrind介绍

​ valgrind是一个开源的,检测内存泄漏的工具,通常在linux下使用,除此之外,他还能检测内存管理错误,线程bug等错误。粗浅的来讲,valgrind由两部分构成,一部分用来模拟cpu和内核,被称为framework(框架),一部分是他用来检测各种错误信息的插件工具。其中的插件包括:

memcheck:是valgrind最重要的工具之一,是一个重量级的内存检查器,它可以帮我们检测是否有使用未初始化的内存,以及内存泄漏,访问越界之类的问题。

callgrind:可以用来统计函数的互相调用情况。可以用来统计某个函数被调用了几次,以及他们的调用关系。

cachegrind:cache分析器,可以精准的指出cache的丢失与命中。还可以统计cache命中与丢失的次数,让我们了解我们程序堆栈的使用情况。

helgrind:主要用来检测线程资源的竞争问题,比如POSIX pthreads API的误用。由锁排序导致的死锁。以及数据的竞争问题等。

massif:堆栈分析器。它可以统计堆和栈使用的内存大小是多少。

extension:可以利用core的特性自己编辑的内存调试工具。

在这里插入图片描述

ps:valgrind相当于一个沙盒,指定的程序会在他模拟的cpu和内核中去运行,所以我们尽量不要使用他来进行性能测试,这是不合理的!。

二,valgrind通用命令

#指定使用的工具
valgrind --tool=toolname program#指定输出日志的名字
--log-file=logname.log#打印帮助信息。
-h --help #显示valgrind的版本
--version 
显示valgrind内核的版本,每个工具都有各自的版本。 #只打印错误信息
-q --quiet #打印更加详细的信息。
-v --verbose 

三,memcheck的使用

​ memcheck是valgrind的默认工具,可以与 valgrind program 一起运行,不指定工具时,便默认使用memcheck,即 valgrind --tool=memcheck。运行 Memcheck 时程序运行速度要比正常运行时慢 10-30 倍。这也是为什么我们一般使用它进行功能测试,而不是性能测试的原因。

1,选项

#启用后(=yes 或 =full 或 =summary),Memcheck会在客户端程序完成后搜索内存泄漏。其默认值为summary,它输出找到的泄漏数。其他可能的值为 yes 和 full,这两个选项都会给出每个泄漏的详细情况。
#禁用(=no)禁用内存泄漏检查。 
--leak-check=#启用后(将其设定为 =yes),Memcheck 会报告使用未定义值报告的错误。
#禁用时(将其设定为 =no),则不会报告未定义值错误。默认启用这个选项。禁用该选项会稍稍提高 Memcheck 速度。
--undef-value-errors=#可让用户指定一个或者多个 Memcheck 检查时应该忽略的范围。多个范围使用逗号分开,例如:--ignore-ranges=0xPP-0xQQ,0xRR-0xSS。 
--ignore-ranges=#输出结果为。。。文件
--log-file=filename#是否打印间接泄漏日志
--show-reachable=yes.

2,错误类型

1.非法读写错误[invalid read of size 4] :读写了被释放的内存,没有被分配的内存等,还有内存访问越界等问题导致的。

2.使用未初始化的内存[Conditional jump or move depends on uninitialised value]:使用了没有初始化的值,例如使用没有被初始化的局部变量;或使用了没有初始化的堆。

3.[syscall param write(buf) points to uninitilaised bytes]:buffer不可用,例如在使用snprintf()时,写入的字符串大于存储的buffer,就会爆出这个错误。

4.非法释放[invalid free()]:重复释放内存块(即double free),或者指针没有指向内存的起始位置。

5.使用不适当的释放函数释放[Mismatched free()/delete/delete[]]:

  • 如果与分配 malloc, calloc, realloc, valloc或者 memalign,必须使用free。
  • 如果分配new,必须使用delete。

6.内存块重叠[source and destination overlap in memcpy(,)]:比如使用 memcpy 函数时源地址和目标地址发生重叠。

7.Fishy argument values[Argument ‘size’ of function malloc has a fishy (possibly negative) value: -3]:需要的内存不合理,例如需要-1的内存,或者很大的内存,无法分配。

3,使用实例与分析

#例如执行./a.out  -p 32903 -i 127.0.0.1 -b 0 -t 10这样的程序。
#那么需要用valgrind的时候,用如下命令
valgrind --tool=memcheck --leak-check=yes --log-file=check.log ./${OBJ_NAME}.o  -p 32903 -i 127.0.0.1 -b 0 -t 10 

valgrind 将内存泄漏分为 4 类:并且默认情况下,只会打印明确泄漏 和可能泄漏,如果需要打印 间接泄漏,需要加上选项 --show-reachable=yes.

明确泄漏(definitely lost):表示某段内存还没有被释放,但是已经没有指针指向它了,所以明确了这里一定发生了内存释放。
间接泄漏(indirectly lost):某一段内存没有被释放,指向它的指针仍然存在,但是,存放这个指针的内存已经被释放了。
可能泄漏(possibly lost):指针存在,但并不指向内存头地址,而是指向内存内部的位置。
仍可访达(still reachable):指针一直存在并指向首地址,直至程序退出时内存还没被释放。例如指针ptr=malloc()了一段内存,直至程序结束,ptr仍然指向malloc分配的内存的首地址,并且该内存仍然没有没释放。

明确泄漏和间接泄漏毫无疑问是必须修复的,间接泄漏往往在明确泄漏被修复后便解决了,可能泄漏要看我们的函数是不是那样设计的,需要我们检查后定论,而任可访达,也需要我们判断,如果程序正常退出后,仍然有仍可访达,那么也是需要修复的,一般是在程序的结尾忘记了free()或者close()某些句柄造成的。如果程序,被信号强行终止,那么就可能就并不是泄漏,只是程序还未走到free()的地方便结束了程序造成的。

#日志输出后,我们一般先看HEAP SUMMARY(堆总结内存) 以及 LEAK SUMMARY(内存泄漏总结)
==27801== HEAP SUMMARY:
==27801==   in use at exit: 215,528 bytes in 379 blocks
==27801==   total heap usage: 801 allocs, 422 frees, 274,889 bytes allocated
==27801== 	#分配了801次内存,但是只释放了422次。#leak summary会总结所有类型的内存泄漏,泄漏多少字节,在多少个blocks里面泄漏了。
==27756== LEAK SUMMARY:
==27756==    definitely lost: 520 bytes in 1 blocks
==27756==    indirectly lost: 61,800 bytes in 173 blocks
==27756==    possibly lost: 152,896 bytes in 204 blocks
==27756==    still reachable: 312 bytes in 1 blocks
==27756==    suppressed: 0 bytes in 0 blocks
#统计了使用valgrind的某些参数取消了特定库的某些错误,会被归结到suppressed。
格式
at {地址、函数名、模块或代码行}
by {地址、函数名、代码行}
by …{逐层依次显示调用堆栈}
Address 0x??? {描述地址的相对关系}
#例:明确泄漏分析
#泄漏情况和泄漏类型
==27703== 62,320 (520 direct, 61,800 indirect) bytes in 1 blocks are definitely lost in loss record 116 of 117
==27703==    at 0x48483D0: malloc (vg_replace_malloc.c:262)    #at...在哪里分配的内存
==27703==    by 0x48CC3B3: sqlite3MemMalloc (sqlite3.c:23980)  #by...分配的内存都在哪里被使用了
==27703==    by 0x48B380F: mallocWithAlarm (sqlite3.c:27862)
==27703==    by 0x48B3917: sqlite3Malloc (sqlite3.c:27892)
==27703==    by 0x49925AB: openDatabase (sqlite3.c:28134)
==27703==    by 0x487345F: sqlite3_open_database_table (in /home/。。。/。。。/。。。/。。。/libname.so)#(显示是哪一个库的哪一个函数发生的内存泄漏)
#最后使用这段内存的函数是sqlite3_open_database_table,一般就是这里,或者是调用了这个函数后忘记释放了内存导致的。

四,一些使用经验

1、sqlite3_get_table()释放

int sqlite3_get_table(sqlite3 *db,              /* Database handle */const char *Sql,         /* SQL query to be executed */char ***Result,        /* Pointer to array of result rows */int *nRow,               /* Number of result rows written here */int *nColumn,            /* Number of result columns written here */char **Errmsg           /* Error msg written here */
);

这个函数会执行 SQL 语句并将结果存储在一个二维字符数组中,然后返回指向这个数组的指针。它在内部会使用malloc来分配足够的内存来容纳查询结果。由于sqlite3_get_table使用了malloc,所以在使用完查询结果后,必须调用sqlite3_free_table () 来释放由sqlite3_get_table 分配的内存(即需要释放掉result结果),以避免内存泄漏问题。这个函数会释放整个结果数组及其内部的字符串数组所分配的内存。除此之外,如果在调用 sqlite3_get_table函数时出现了错误(比如语法错误、查询失败等),则 Errmsg指向的内存将被写入错误信息。在处理完错误后,调用者需要调用sqlite3_free释放Errmsg 指向的内存,以避免内存泄漏。

2、getaddrinfo()释放

int getaddrinfo(const char *node, const char *service,const struct addrinfo *hints, struct addrinfo **res);

函数是用于执行主机名到 IP 地址以及服务名到端口号的转换的函数,getaddrinfo 函数会返回一个 addrinfo 结构体链表,因为是使用链表存储,每个节点表示一个可能的主机名和服务名对应的 IP 地址和端口号。这些 addrinfo 结构体的内存是在 getaddrinfo 函数内部使用 malloc 动态分配的。因此,在使用 getaddrinfo 函数时,需要注意在使用完返回的结果后,调用 freeaddrinfo 函数来释放动态分配的内存,避免内存泄漏。

3,else省略导致的内存泄漏

#根据以下信息,我们可以了解到内存泄漏大抵是发生在sqlite3_open_database_table函数中,又检查了自己的主函数后发现已经free过db了在程序结尾处,所以我们基本确定是函数内部的问题。在进行更改。
==9359== 62,320 (520 direct, 61,800 indirect) bytes in 1 blocks are definitely lost in loss record 116 of 117 
==9359==    at 0x48483D0: malloc (vg_replace_malloc.c:262)
==9359==    by 0x48CC3B3: sqlite3MemMalloc (sqlite3.c:23980)
==9359==    by 0x48B380F: mallocWithAlarm (sqlite3.c:27862)
==9359==    by 0x48B3917: sqlite3Malloc (sqlite3.c:27892)
==9359==    by 0x49925AB: openDatabase (sqlite3.c:28134)
==9359==    by 0x48734C7: sqlite3_open_database_table (in /home/。。。/。。。/lib/libmylib.so)
==9359== 
//改前:
==27756== LEAK SUMMARY:
==27756==    definitely lost: 520 bytes in 1 blocks
==27756==    indirectly lost: 61,800 bytes in 173 blocks
==27756==    possibly lost: 152,896 bytes in 204 blocks
==27756==    still reachable: 312 bytes in 1 blocks
==27756==    suppressed: 0 bytes in 0 blocks//更改之前的代码
int sqlite3_open_database_table(const char *db_name)
{   int                         rv = -1; char                        sql_str[SQL_COMMAND_LEN] = {0};char                        *err_msg = NULL;if ( db_name == NULL ){   log_error("%s() Invalid input arguments\n", __func__);return -1; }   //if database has exist, just open it if ( 0 == access(db_name, F_OK) ){   if ( SQLITE_OK != sqlite3_open(db_name, &db) ){   log_error("open file %s error\n", db_name);return -1; }   else{   log_info("open database file '%s' success\n", db_name);}   }   //注意,我们这里省略了else,导致这里这里无论如何都会被执行,也就是又多malloc了一个db,//正是这个原因,导致了内存泄漏。如果一定要这么用,需要free两次。if (  sqlite3_open(db_name, &db) != SQLITE_OK ){   log_error("create open file %s error\n", db_name);return -1; }   //database has open,create table and open itsnprintf(sql_str, SQL_COMMAND_LEN,"CREATE TABLE IF NOT EXISTS %s(dev_name text,meas_time text,temp real);", TABLE_NAME);if ( sqlite3_exec(db, sql_str, 0, 0, &err_msg) != SQLITE_OK ){   log_error("create table: %s failure:%s\n", TABLE_NAME, err_msg);sqlite3_free(err_msg);sqlite3_close(db);unlink(db_name);return -1; }   sqlite3_free(err_msg);return 0;
}
//改后:
==5477== LEAK SUMMARY:
==5477==    definitely lost: 0 bytes in 0 blocks
==5477==    indirectly lost: 0 bytes in 0 blocks
==5477==    possibly lost: 152,896 bytes in 204 blocks
==5477==    still reachable: 360 bytes in 2 blocks
==5477==    suppressed: 0 bytes in 0 blocks//更改后的代码
int sqlite3_open_database_table(const char *db_name)
{   int                         rv = -1; char                        sql_str[SQL_COMMAND_LEN] = {0};char                        *err_msg = NULL;if ( db_name == NULL ){   log_error("%s() Invalid input arguments\n", __func__);return -1; }   //if database has exist, just open it if ( 0 == access(db_name, F_OK) ){   if ( SQLITE_OK != sqlite3_open(db_name, &db) ){   log_error("open file %s error\n", db_name);return -1; }   else{   log_info("open database file '%s' success\n", db_name);}   }   else//正常的判断,加入else后,sqlite3——open只执行一个,所以只释放一次即可。{   if (  sqlite3_open(db_name, &db) != SQLITE_OK ){   log_error("create open file %s error\n", db_name);return -1; }   //database has open,create table and open itsnprintf(sql_str, SQL_COMMAND_LEN,"CREATE TABLE IF NOT EXISTS %s(dev_name text,meas_time text,temp real);", TABLE_NAME);}   if ( sqlite3_exec(db, sql_str, 0, 0, &err_msg) != SQLITE_OK ){   log_error("create table: %s failure:%s\n", TABLE_NAME, err_msg);sqlite3_free(err_msg);sqlite3_close(db);unlink(db_name);return -1; }   sqlite3_free(err_msg);return 0;
}

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

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

相关文章

爬虫学习笔记-数美验证

测试网址:智能验证码体验_图片验证码_数美科技数美科技智能验证码在线体验,智能识别风险用户级别,自行切换智能验证码难度及类型,提供滑动、拼图、点选、数字、动态等多种智能验证码服务,精准拦截机器行为。https://ww…

R语言详解二

一&#xff0c;列表详解 创建一个列表 > myList<-list(id2,name"张三",age20) > myList $id [1] 2$name [1] "张三"$age [1] 20 获取第一个元素 > myList[[2]] [1] "张三" 获取第一个子列表 > myList[2] $name [1] "张…

20240309web前端_第四次作业_完成随机点名程序

要求 一、结合抽奖案例完成随机点名程序&#xff0c;要求如下: 1.点击点名按钮&#xff0c;名字界面随机显示&#xff0c;按钮文字由点名变为停止 2.再次点击点名按钮&#xff0c;显示当前被点名学生姓名&#xff0c;按钮文字由停止变为点名 3.样式请参考css及html自由发挥完成…

解读宁波IATF16949认证:开启成功之门的钥匙️

&#x1f449;解读宁波IATF16949认证&#xff1a;&#x1f970;开启成功之门的钥匙&#x1f5dd;️ &#x1f432;在风起云涌的&#x1f4fa;商业浪潮中&#xff0c;&#x1f6b6;每一个追求卓越的&#x1f685;企业都渴望找到一把&#x1f511;开启成功之门的钥匙。&#x1f3…

Vscode配置C/C++编程环境@配置C和CPP的运行和调试环境@配置过程的相关问题@中文文件名乱码@build和debug方案组合配置

文章目录 abstractgcc/g文档和用法常见用例 目录.vscode中的相关文件说明tasks.jsonlaunch.jsonc_cpp_properties.json IDE或编辑器配置vscode配置相关指令和快捷键默认task配置和取消默认 配置文件C/C共用一组tasks.json/launch.json文件?关于注释内容示例&#x1f47a;tasks…

linux安装MySQL8.0,密码修改权限配置等常规操作详解

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

面试二十一、红黑树

性质&#xff1a; 插入&#xff1a; 旋转&#xff1a;

公司网页制作需要多少钱

公司网页制作需要多少钱&#xff1f;这是一个非常常见的问题。答案取决于您需要的功能和设计。一些小型企业网站可能只需要一些基本的功能&#xff0c;花费可能低至几百美元&#xff0c;而一些大型企业网站可能需要高级功能和设计&#xff0c;可能需要几万美元。 以下是一些考虑…

阿里云盘小白羊版3.24.33113

网盘下载 里云盘小白羊版是一款在官方客户端基础上进行二次开发制作而成的第三方客户端&#xff0c;它拥有完善的云盘客户端功能&#xff0c;支持文件的列出、移动、重命名、在线预览、下载文件、创建点连接等等一系列功能&#xff0c;官方客户端所拥有的的功能它都有&#xf…

matlab 对数坐标画图,及在曲线上加竖直线

matlab 对数坐标画图 方法一&#xff1a;直接对x、y值取对数&#xff0c;然后画图 plot(log(x), log(y), m, LineWidth,1, Marker,.);% ,Color,#EDB120 方法二&#xff1a;将x、y轴刻度改为对数形式 plot(x, y, r, LineWidth,1, Marker,); ax gca();% 获取当前坐标句柄 ax…

.NET/C#汇总 —— 数据库SQL查询(附建表语句)

1.⽤⼀条SQL 语句 查询出每⻔课都⼤于80 分的学⽣姓名 建表语句: create table tableA ( name varchar(10), kecheng varchar(10), fenshu int(11) )DEFAULT CHARSET = utf8;插⼊数据 insert into tableA values (张三,语⽂,81); insert into tableA values (张三,数学,75)…

spring boot3单模块项目工程搭建-下(个人开发模板)

⛰️个人主页: 蒾酒 &#x1f525;系列专栏&#xff1a;《spring boot实战》 &#x1f30a;山高路远&#xff0c;行路漫漫&#xff0c;终有归途 目录 写在前面 上文衔接 常用依赖介绍以及整合 web组件 测试组件 样板代码生成 数据库连接器 常用工具包 面向切面编…

覆盖完整产业链“2024长三角消费电子产业展会”11月在南京召开

2024长三角消费电子产业展览会将与11月份在南京国际博览中心盛大开幕。作为一场集智慧生活、智慧健康、人工智能、雷达技术、智能机器人、5G通信和自动驾驶等众多领域于一体的消费电子产业盛会&#xff0c;本届展会不仅全面覆盖了消费电子产业链的各个环节&#xff0c;更致力于…

【vue2+onlyoffice】基础预览demo运行+问题解决

之前其实写过Onlyoffice的使用&#xff0c;但是写得不太完整&#xff0c;这次补充下。 一、OnlyOffice简介 ONLYOFFICE&#xff0c;是一个包含常用办公套件&#xff0c;Word 、Excel、PPT大办公套件搬到了云端&#xff0c;只需要一个浏览器即可以在线使用 Office 的各种功能。…

html、css、京东移动端静态页面,资源免费分享,可作为参考,提供InsCode在线运行演示

CSDN将我上传的免费资源私自变成VIP专享资源&#xff0c;且作为作者的我不可修改为免费资源&#xff0c;不可删除&#xff0c;寻找客服无果&#xff0c;很愤怒&#xff0c;&#xff08;我发布免费资源就是希望大家能免费一起用、一起学习&#xff09;&#xff0c;接下来继续寻找…

软考 系统架构设计师系列知识点之软件可靠性基础知识(4)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之软件可靠性基础知识&#xff08;3&#xff09; 所属章节&#xff1a; 第9章. 软件可靠性基础知识 第1节 软件可靠性基本概念 9.1.2 软件可靠性的定量描述 从软件可靠性的定义可以看到&#xff0c;软件的可靠性可以基…

c++初阶-----STL---vector

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

SecuPress Pro 专业级WordPress网站安全防护插件优化版

下载地址&#xff1a;SecuPress Pro 专业版.zip SecuPress Pro&#xff1a;专业的WordPress安全解决方案 如果您没有时间进行每周扫描&#xff0c;SecuPress Pro将是您的理想选择。SecuPress Pro提供了所有SecuPress Free的功能&#xff0c;同时还增加了一些高级选项&#xff…

CUDA的开发技术难点

CUDA的开发技术难点不仅包括对并行计算模型的理解&#xff0c;还涉及到内存管理、线程同步、性能优化等多个方面。开发者需要不断学习和实践&#xff0c;才能熟练掌握CUDA编程。CUDA的开发技术难点主要集中在以下几个方面。北京木奇移动技术有限公司&#xff0c;专业的软件外包…

时装购物系统,基于 SpringBoot+Vue+MySql 开发的前后端分离的时装购物系统分析设计与实现

目录 一. 前言 二. 功能模块 2.1. 管理员功能模块 2.2. 用户功能模块 2.3. 前台首页功能模块 三. 部分代码实现 四. 源码下载 一. 前言 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的…