sudo apt install valgrind
2.检查需要进行分析的代码,未编译时,需要进行编译gcc -g myfile.c -o your_program
3.执行简易分析数据获取valgrind --tool=callgrind ./your_program
特点:Valgrind 将自动启动 Callgrind 工具,并执行你的程序程序的执行过程将被 Valgrind 记录下来以进行后续分析指定分析数据获取(常用)valgrind --tool=memcheck [options] executable [args]
举例:valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all --log-file=./valgrind-peony.txt peony
特点:可以定制分析指定内容,并配置各项输出结果等常用参数说明:-leak-check=<参数>:控制内存泄漏检查的级别no:不进行内存泄漏检查summary:输出内存泄漏的摘要信息full:输出详细的内存泄漏信息,包括泄漏的内存块列表yes(默认值):等同于–leak-check=full-show-leak-kinds=<参数>:显示所有类型的内存泄漏definite:只显示确定性的内存泄漏indirect:只显示间接内存泄漏其他泄漏引起possible:显示可能的内存泄漏包括可能的直接和间接泄漏all(默认值):显示所有类型的内存泄漏-log-file=<文件名>:将Valgrind的输出结果保存到指定的日志文件中,而不是直接打印到终端上<文件名>:指定要保存Valgrind输出结果的文件名,可以是相对路径或绝对路径注意:确保指定的文件名是有效和可写的,以免出现保存输出结果失败的情况-show-reachable=<yes|no>:显示可访问但未释放的内存块,默认值为no,当设置为yes时,会显示可访问但未释放的内存块的详细信息,主要用于查找潜在的内存泄漏-track-origins=<yes|no>:追踪未初始化的内存块的来源默认值为no,当设置为yes时,会将未初始化的内存块的内容标记为来源未知(origin unknown),主要用于检测未初始化值的错误4.分析SUMMARYSUMMARY部分是Valgrind输出的总结信息,提供了检测到的内存错误的统计和摘要它包括了内存泄漏的数量、错误的数量以及性能相关的信息泄漏类型如下:01“Definitely lost”(绝对泄漏)表示程序分配的内存块没有被释放,并且没有任何指针指向它们,导致无法访问和释放这些内存,可能是由于分配后忘记释放、指针丢失或错误的内存管理引起的02“Possibly lost”(可能泄漏)表示程序分配的内存块没有被释放,但仍存在相关指针指向它们,可能由于指针丢失或错误的内存管理引起,但存在可能指针仍可访问相关内存的情况03“Indirectly lost”(间接泄漏)表示由于前面的内存泄漏导致的其他内存泄漏,前面的错误泄漏了内存块,而这些被泄漏的内存块又是其他内存块的分配者04“Reachable”(可访问的)表示程序结束时仍然有一些未释放的内存块,但它们仍然可(有指针指向)不被视为内存泄漏,可能是由于程序设计需要保留这些内存块,比如全局变量等05“suppressed”(受抑制的)当Valgrind检测到某个特定错误或警告时,可能会在输出结果中显示“suppressed”来指示已抑制相关信息,抑制的信息通常与先前报告的错误或警告相关联,可能是相同的错误或警告,但由于某种原因被抑制,不会再次输出抑制,通常发生在相关的错误或警告已经被准确地报告过,并且由于大量的重复发生,Valgrind选择抑制该信息ERROR/MEMORY LEAK DETAILS列出每个错误和内存泄漏的相关信息这些信息包括错误类型、错误位置、错误堆栈跟踪、泄漏的内存块的地址等ERROR TYPESInvalid read/write:非法的读取或写入操作Uninitialized value:使用未初始化的值Invalid free/delete:释放了无效的内存Mismatched free/delete:释放内存时不匹配Memory leak:内存泄漏问题Use of unaddressable memory:使用了不可寻址的内存Incorrect order of deallocation:释放内存的顺序错误Overlapping source and destination blocks:源和目标内存块重叠MEMORY LEAK DETAILS检测到内存泄漏,提供有关泄漏的详细信息包括泄漏的内存块的大小、泄漏的位置、内存块的地址等STACK TRACE在某些错误中,Valgrind会提供错误发生时的堆栈跟踪信息5.处理针对valgrind给出的相关信息可以从以下步骤进行处理:定位泄漏源使用Valgrind提供的堆栈跟踪信息,找到导致泄漏的代码路径和分配位置确认正确释放检查相应的代码,在合适的位置释放这些未释放的内存块验证修复效果重新运行程序并使用Valgrind验证是否解决了绝对泄漏问题注意细节确保在释放内存之前,所有相关指针都已经被正确处理和释放调整代码逻辑如果发现了不必要的可访问内存块,进行必要的代码调整和释放内存的操作6.分析说明举例此处以一个存在绝对漏洞的分析结果进行分析说明:首先,运行按照指令打开文件管理器,运行及常规操作完成后,关闭文件管理器,可以得到一个valgrind-peony.txt的分析结果,打开分析文本找到一条Definitely lost的记录,并进行分析,将记录结果列举如下:==295098== 8,408 (1,392 direct, 7,016 indirect) bytes in 1 blocks are definitely lost in loss record 2,355 of 2,361==295098== at 0x483BE63: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)==295098== by 0x105A25AD: Qt5UKUIStyle::Qt5UKUIStyle(bool, bool, QString) (in /usr/lib/x86_64-linux-gnu/qt5/plugins/styles/libqt5-style-ukui.so)==295098== by 0x105A07F4: Qt5UKUIStylePlugin::create(QString const&) (in /usr/lib/x86_64-linux-gnu/qt5/plugins/styles/libqt5-style-ukui.so)==295098== by 0x5553BF9: QStyleFactory::create(QString const&) (in /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.12.12)==295098== by 0x557B2DF: QProxyStyle::QProxyStyle(QString const&) (in /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.12.12)==295098== by 0x1041E58C: UKUI::ProxyStyle::ProxyStyle(QString const&) (in /usr/lib/x86_64-linux-gnu/qt5/plugins/styles/libukui-proxy-style.so)==295098== by 0x1041FD3A: UKUI::ProxyStylePlugin::create(QString const&) (in /usr/lib/x86_64-linux-gnu/qt5/plugins/styles/libukui-proxy-style.so)==295098== by 0x5553BF9: QStyleFactory::create(QString const&) (in /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.12.12)==295098== by 0x54E6041: QApplication::style() (in /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.12.12)==295098== by 0x54E639C: QApplicationPrivate::initialize() (in /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.12.12)==295098== by 0x54E63F7: QApplicationPrivate::init() (in /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.12.12)==295098== by 0x13EC10: SingleApplication::SingleApplication(int&, char, char const, bool, QFlagsSingleApplication::Mode, int) (singleapplication.cpp:40)
上述反馈结果可以得出以下分析:根据Valgrind输出,可以看到loss record 2,355 of 2,361中有8,408字节的内存在1个堆块中被明确地丢失具体的丢失堆块的分配和释放情况如下所示:在函数Qt5UKUIStyle::Qt5UKUIStyle(bool, bool, QString)中,通过operator new(unsigned long)进行了内存分配,但没有相应的释放操作这个失去的堆块在libqt5-style-ukui.so库中的Qt5UKUIStylePlugin::create(QString const&)函数被创建接着由libqt5-style-ukui.so库通过QStyleFactory::create(QString const&)函数创建了QProxyStyle对象QProxyStyle对象进一步由libukui-proxy-style.so库UKUI::ProxyStyle::ProxyStyle (QString const&)函数创建在此之后,又通过libukui-proxy-style.so库中的UKUI::ProxyStylePlugin::create(QString const&)函数通过QStyleFactory::create(QString const&)函数的调用创建了QProxyStyle对象在调用栈的最后,这段丢失的内存是在单独应用程序的构造函数SingleApplication::SingleApplication(int&,char,char const, bool, QFlags<SingleApplication::Mode>, int)中出现的Valgrind的输出表明,在这些函数的执行过程中,没有释放掉先前分配的内存这样的内存泄漏可能会导致程序运行时内存使用过多,最终可能会导致性能下降或崩溃最后进一步修改代码,将未释放的内存进行释放然后再次进行分析验证03使用建议初次使用时,不进行任何操作,待程序启动完成后直接关闭程序用于分析初始化存在的内存泄漏;静态分析,启动程序后不进行任何操作,待2-3小时或足够长的时候后关闭程序用于分析静态程序存在的内存泄漏;指定分析,启动程序后,执行相关操作后关闭程序用于分析功能内存泄漏(图片来源网络,侵删)
0 评论