valgrind 配合 gdb 调试程序
在实际研发过程中,可能会遇到过这样的问题:测试通过 valgrind 验证当前代码存在变量未初始化的问题,但仅通过 valgrind 测试报告,研发无法确认具体的应用场景。本文将通过 valgrind 检测并定位程序中变量未初始化的问题,并给出用户具体的操作场景。
前言
为保证程序的健壮性和可靠性,程序在完成基本的功能测试后,一般来说还要进行内存使用相关的测试。Valgrind 是一个强大的 C 和 C++ 程序调试和性能分析工具。它可以检测内存泄漏、未初始化的内存使用以及其他各种错误。本文将以 MariaDB 为例,通过 valgrind 检测并定位程序中变量未初始化的问题。
使用 valgrind 检测程序错误
- 为说明问题,在 MariaDB 的 mysql_execute_command 函数中添加如下代码:
int unitialized_value;
if (SQLCOM_SHOW_TABLES != thd_sql_command(thd)) {
unitialized_value = 0;
}
if (unitialized_value) {
sql_print_information("Unitialized value");
}
- 使用 valgrind 运行 mariadbd 程序
valgrind --tool=memcheck --trace-children=yes --track-origins=yes \
--leak-check=full --show-leak-kinds=all \
--log-file=./valgrind.log --error-limit=no \
/home/dbdev/mariadb/bin/mariadbd --defaults-file=./etc/mariadb.cnf &
- 登录 MariaDB server
/home/dbdev/mariadb/bin/mysql -S /home/dbdev/mariadb/data/mysqld.sock
- 执行如下 SQL 语句
MariaDB [(none)]>
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sakila |
| sys |
| test |
| world_x |
+--------------------+
7 rows in set (0.486 sec)
MariaDB [(none)]> use test
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
MariaDB [test]> show tables;
+----------------+
| Tables_in_test |
+----------------+
| v1 |
+----------------+
1 row in set (0.096 sec)
- 查看 valgrind.log 日志
==5432== Memcheck, a memory error detector
==5432== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==5432== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==5432== Command: /home/dbdev/mariadb/bin/mariadbd --defaults-file=./etc/mariadb.cnf
==5432== Parent PID: 1055
==5432==
==5432== Warning: set address range perms: large range [0x124746000, 0x164746000) (defined)
==5432== Warning: set address range perms: large range [0x164746000, 0x1a4746000) (defined)
==5432== Warning: set address range perms: large range [0x124746000, 0x144063000) (defined)
==5432== Warning: set address range perms: large range [0x124746000, 0x144063000) (defined)
==5432== Thread 20:
==5432== Conditional jump or move depends on uninitialised value(s)
==5432== at 0xAA9991: mysql_execute_command(THD*, bool) (sql_parse.cc:3482)
==5432== by 0xAB52D3: mysql_parse(THD*, char*, unsigned int, Parser_state*) (sql_parse.cc:7779)
==5432== by 0xAA4E5A: dispatch_command(enum_server_command, THD*, char*, unsigned int, bool) (sql_parse.cc:1892)
==5432== by 0xAA3C74: do_command(THD*, bool) (sql_parse.cc:1405)
==5432== by 0xC9381C: do_handle_one_connection(CONNECT*, bool) (sql_connect.cc:1416)
==5432== by 0xC9359C: handle_one_connection (sql_connect.cc:1318)
==5432== by 0x11D4C72: pfs_spawn_thread (pfs.cc:2201)
==5432== by 0x5330B42: start_thread (pthread_create.c:442)
==5432== by 0x53C1BB3: clone (clone.S:100)
==5432== Uninitialised value was created by a stack allocation
==5432== at 0xAA977B: mysql_execute_command(THD*, bool) (sql_parse.cc:3444)
==5432==
valgrind 配合 gdb 调试程序错误
存在的问题
测试生成了 valgrind 测试报告 valgrind.log,测试报告内容如下:
==5432== Memcheck, a memory error detector
==5432== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==5432== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==5432== Command: /home/dbdev/mariadb/bin/mariadbd --defaults-file=./etc/mariadb.cnf
==5432== Parent PID: 1055
==5432==
==5432== Warning: set address range perms: large range [0x124746000, 0x164746000) (defined)
==5432== Warning: set address range perms: large range [0x164746000, 0x1a4746000) (defined)
==5432== Warning: set address range perms: large range [0x124746000, 0x144063000) (defined)
==5432== Warning: set address range perms: large range [0x124746000, 0x144063000) (defined)
==5432== Thread 20:
==5432== Conditional jump or move depends on uninitialised value(s)
==5432== at 0xAA9991: mysql_execute_command(THD*, bool) (sql_parse.cc:3482)
==5432== by 0xAB52D3: mysql_parse(THD*, char*, unsigned int, Parser_state*) (sql_parse.cc:7779)
==5432== by 0xAA4E5A: dispatch_command(enum_server_command, THD*, char*, unsigned int, bool) (sql_parse.cc:1892)
==5432== by 0xAA3C74: do_command(THD*, bool) (sql_parse.cc:1405)
==5432== by 0xC9381C: do_handle_one_connection(CONNECT*, bool) (sql_connect.cc:1416)
==5432== by 0xC9359C: handle_one_connection (sql_connect.cc:1318)
==5432== by 0x11D4C72: pfs_spawn_thread (pfs.cc:2201)
==5432== by 0x5330B42: start_thread (pthread_create.c:442)
==5432== by 0x53C1BB3: clone (clone.S:100)
==5432== Uninitialised value was created by a stack allocation
==5432== at 0xAA977B: mysql_execute_command(THD*, bool) (sql_parse.cc:3444)
==5432==
研发进能够根据该堆栈信息查询到未初始化值的设置地方及使用地方。但是不清楚具体是哪种操作(具体 SQL 语句)导致的,因为具体应用中未初始化 unitialized_value 的地方可能存在多处。
valgrind 配合 gdb 调试 MariaDB
- 开启终端 T1,使用 gdb 模式运行 valgrind,即指定 --vgdb=yes --vgdb-error=0 选项运行 valgrind
valgrind --tool=memcheck --trace-children=yes --track-origins=yes \
--vgdb=yes --vgdb-error=0 --leak-check=full \
--show-leak-kinds=all --log-file=./valgrind.log \
--error-limit=no /home/dbdev/mariadb/bin/mariadbd \
--defaults-file=./etc/mariadb.cnf &
- 开启终端 T2,使用 gdb 调试运行 mariadbd
gdb /home/dbdev/mariadb/bin/mariadbd
GNU gdb (Ubuntu 13.1-2ubuntu2) 13.1
Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from bin/mariadbd...
(gdb)
(gdb)
- 终端 T1 打开 valgrind.log
cat valgrind.log
==7516== Memcheck, a memory error detector
==7516== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==7516== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==7516== Command: /home/dbdev/mariadb/bin/mariadbd --defaults-file=./etc/mariadb.cnf
==7516== Parent PID: 1055
==7516==
==7516== (action at startup) vgdb me ...
==7516==
==7516== TO DEBUG THIS PROCESS USING GDB: start GDB like this
==7516== /path/to/gdb /home/dbdev/mariadb/bin/mariadbd
==7516== and then give GDB the following command
==7516== target remote | /usr/bin/vgdb --pid=7516
==7516== --pid is optional if only one valgrind process is running
==7516==
- 将 "target remote | /usr/bin/vgdb --pid=7516" 输入到 T2 执行
(gdb) target remote | /usr/bin/vgdb --pid=7516
Remote debugging using | /usr/bin/vgdb --pid=7516
relaying data between gdb and process 7516
warning: remote target does not support file transfer, attempting to access files from local filesystem.
Reading symbols from /lib64/ld-linux-x86-64.so.2...
Reading symbols from /usr/lib/debug/.build-id/bf/789e981fb305f374f3975a4b248eb4cd207ce6.debug...
0x00000000040202f0 in _start () from /lib64/ld-linux-x86-64.so.2
- T2 输入 c 命令后程序自动运行,后续用户连接到 MariaDB 实例执行 SQL 语句时,valgrind 在检测到代码可能存在问题时会自动激活 valgrind 内部设置的断点,此时就可以观察程序内部的变量是否正确
(gdb) target remote | /usr/bin/vgdb --pid=7516
Remote debugging using | /usr/bin/vgdb --pid=7516
relaying data between gdb and process 7516
warning: remote target does not support file transfer, attempting to access files from local filesystem.
Reading symbols from /lib64/ld-linux-x86-64.so.2...
Reading symbols from /usr/lib/debug/.build-id/bf/789e981fb305f374f3975a4b248eb4cd207ce6.debug...
0x00000000040202f0 in _start () from /lib64/ld-linux-x86-64.so.2
(gdb) c
Continuing.
- T1 登录 MariaDB 实例,执行如下 SQL 语句,该操作会激活 T2 的 gdb 断点
MariaDB [(none)]> use test
- T2 查看堆栈信息,输出当前的 SQL 语句信息,通过这种方式,我们可以清楚的知道具体是什么操作导致了未初始化内存的使用
(gdb) bt
#0 0x0000000000aa99a0 in mysql_execute_command (thd=0x1aa290f88, is_called_from_prepared_stmt=false) at /home/dbdev/workspace/server/sql/sql_parse.cc:3482
#1 0x0000000000ab52e4 in mysql_parse (thd=0x1aa290f88, rawbuf=0x1aa30bf20 "show tables", length=11, parser_state=0x1aa51b1f0) at /home/dbdev/workspace/server/sql/sql_parse.cc:7779
#2 0x0000000000aa4e5b in dispatch_command (command=COM_QUERY, thd=0x1aa290f88, packet=0x1aa29b479 "show tables", packet_length=11, blocking=true) at /home/dbdev/workspace/server/sql/sql_parse.cc:1892
#3 0x0000000000aa3c75 in do_command (thd=0x1aa290f88, blocking=true) at /home/dbdev/workspace/server/sql/sql_parse.cc:1405
#4 0x0000000000c9382d in do_handle_one_connection (connect=0x1aa28f0c8, put_in_cache=true) at /home/dbdev/workspace/server/sql/sql_connect.cc:1416
#5 0x0000000000c935ad in handle_one_connection (arg=0x1aa28f0c8) at /home/dbdev/workspace/server/sql/sql_connect.cc:1318
#6 0x00000000011d4c83 in pfs_spawn_thread (arg=0x1aa290898) at /home/dbdev/workspace/server/storage/perfschema/pfs.cc:2201
#7 0x0000000005330b43 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
#8 0x00000000053c1bb4 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:100
(gdb) p thd->query_string
$1 = {string = {str = 0x1aa30bf20 "show tables", length = 11}, cs = 0x24cbda0 <my_charset_utf8mb3_general_ci>}
valgrind 配合 gdb 调试程序的更多相关文章
- 用GDB调试程序(一)
http://blog.csdn.net/haoel/article/details/2879 用GDB调试程序 GDB概述———— GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具.或 ...
- Linux下使用GDB调试程序
问题描述: Linux下使用GDB调试程序 问题解决: (1)生成调试文件 注: 使用命令 gdb IOStream.c -o IOStre ...
- 用gdb调试程序笔记: 以段错误(Segmental fault)为例
用gdb调试程序笔记: 以段错误(Segmental fault)为例[转] 1.背景介绍2.程序中常见的bug分类3.程序调试器(如gdb)有什么用4.段错误(Segmental fault)介绍5 ...
- 用GDB调试程序
转自:http://blog.csdn.net/haoel/article/details/2879 是一篇从基础讲gdb的博文 用GDB调试程序 GDB概述---- GDB是GNU开源组织发布的一个 ...
- gdb调试程序函数名为问号,什么原因?step by step解决方案
gdb调试程序函数名为问号,什么原因? http://bbs.chinaunix.net/thread-1823649-1-1.html http://www.bubuko.com/infodetai ...
- 用gdb调试程序(Linux环境)
一般来说,GDB主要帮忙你完成下面四个方面的功能: 1.启动你的程序,可以按照你的自定义的要求随心所欲的运行程序. 2.可让被调试的程序在你所指定的调置的断点处停住.(断点可以是条件表达式) ...
- [Z] 用GDB调试程序
原文:http://blog.csdn.net/haoel/article/details/2879 用GDB调试程序 GDB概述———— GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工 ...
- 用 GDB 调试程序
Linux 包含了一个叫 gdb 的 GNU 调试程序. gdb 是一个用来调试 C 和 C++ 程序的强力调试器. 它使你能在程序运行时观察程序的内部结构和内存的使用情况. 以下是 gdb 所提供的 ...
- 转载 gdb调试程序
转载自csdn,作者haoel,链接http://blog.csdn.net/haoel/article/details/2879 用GDB调试程序 GDB概述———— GDB是GNU开源组织发布的一 ...
- Linux高级编程--04.GDB调试程序(查看数据)
查看栈信息 当程序被停住了,你需要做的第一件事就是查看程序是在哪里停住的.当你的程序调用了一个函数,函数的地址,函数参数,函数内的局部变量都会被压入"栈"(Stack)中.你可以用 ...
随机推荐
- 2022-06-16:给定一个数组arr,含有n个数字,都是非负数, 给定一个正数k, 返回所有子序列中,累加和最小的前k个子序列累加和。 假设K不大,怎么算最快? 来自亚马逊。
2022-06-16:给定一个数组arr,含有n个数字,都是非负数, 给定一个正数k, 返回所有子序列中,累加和最小的前k个子序列累加和. 假设K不大,怎么算最快? 来自亚马逊. 答案2022-06- ...
- vue全家桶进阶之路48:Vue3 跨域配置devServer的参数和设置
devServer 是一个用于配置开发服务器的选项对象.它可以用来配置服务器的各种选项,例如代理,端口号,HTTPS 等. 以下是一些常用的 devServer 参数和设置: port:指定开发服务器 ...
- TypeError: Cannot read property ‘make‘ of undefined
这搞个html-webpack-plugin插件进来运行就一大篇报错尴尬 看了一圈又是版本兼容的问题,做下修改.... OK 运行成功
- TypeError: Cannot read property 'getAttribute' of undefined
今天使用echarts + vue 做 图标,运行时提示vue.runtime.esm.js?2b0e:619 [Vue warn]: Error in mounted hook: "Typ ...
- hugp-MemE关键美化
配置front matter 使用vscode snippet快捷生成front matter 参考博客:vs-code-workflows-for-hugo. markdown-snippets-n ...
- Open AI ChatGPT Prompt 学习之基础篇
碎碎念 2023 年,最火的可能就是 openAI 了,其组织代表的产品 chatGTP,相信大家已经有所耳闻.不少同学已经开始着手使用,并截图晒出 ChatGPT 是多么得智能与神奇.而有的同学在使 ...
- 02-面试必会-SSM框架篇
01-什么是 Spring IOC 和 DI ? IOC : 控制翻转 , 它把传统上由程序代码直接操控的对象的调用权交给容 器,通过容器来实现对象组件的装配和管理.所谓的"控制反转&quo ...
- 【大数据OLAP技术新书推荐】 字节跳动、阿里巴巴大厂资深架构师程序员多年实践经验总结《ClickHouse入门、实战与进阶》
ClickHouse 领域集大成之作-ClickHouse 入门进阶实战的标准参考书-日常工作案头必备! 如果需要购买阅读的话,可以点击: https://item.jd.com/1007763561 ...
- python接口自动化封装导出excel方法和读写excel数据
一.首先需要思考,我们在页面导出excel,用python导出如何写入文件的 封装前需要确认python导出excel接口返回的是一个什么样的数据类型 如下:我们先看下不对返回结果做处理,直接接收数据 ...
- 面由 AI 生|ZegoAvatar 捏脸技术解析
一.AI"卷"进实时互动 2021年,元宇宙概念席卷全球,国内各大厂加速赛道布局,通过元宇宙为不同的应用场景的相关内容生态进行赋能.针对"身份"."沉 ...