本节课的核心内容:

  • 将 print 打印结果显示完整
  • 让被 GDB 调试的程序接收信号
  • 函数明明存在,添加断点时却无效

将 print 打印结果显示完整

当使用 print 命令打印一个字符串或者字符数组时,如果该字符串太长,print 命令默认显示不全的,我们可以通过在 GDB 中输入 set print element 0 命令设置一下,这样再次使用 print 命令就能完整地显示该变量的所有字符串了。

void ChatSession::OnGetFriendListResponse(const std::shared_ptr<TcpConnection>& conn)
{std::string friendlist;MakeUpFriendListInfo(friendlist, conn);std::ostringstream os;os << "{\"code\": 0, \"msg\": \"ok\", \"userinfo\":" << friendlist << "}";Send(msg_type_getofriendlist, m_seq, os.str());LOG_INFO << "Response to client: userid=" << m_userinfo.userid << ", cmd=msg_type_getofriendlist, data=" << os.str();
}

以上代码中,当第一次打印 friendlist 这个变量值时,只能显示部分字符串。使用 set print element 0 设置以后就能完整地显示出来了。

(gdb) n
563         os << "{\"code\": 0, \"msg\": \"ok\", \"userinfo\":" << friendlist << "}";
(gdb) p friendlist
$1 = "[{\"members\":[{\"address\":\"\",\"birthday\":19900101,\"clienttype\":0,\"customface\":\"\",\"facetype\":2,\"gender\":0,\"mail\":\"\",\"markname\":\"\",\"nickname\":\"bj_man\",\"phonenumber\":\"\",\"signature\":\"\",\"status\":0,\"userid\":4,"...
(gdb) set print element 0
(gdb) p friendlist
$2 = "[{\"members\":[{\"address\":\"\",\"birthday\":19900101,\"clienttype\":0,\"customface\":\"\",\"facetype\":2,\"gender\":0,\"mail\":\"\",\"markname\":\"\",\"nickname\":\"bj_man\",\"phonenumber\":\"\",\"signature\":\"\",\"status\":0,\"userid\":4,\"username\":\"13811411052\"},{\"address\":\"\",\"birthday\":19900101,\"clienttype\":0,\"customface\":\"\",\"facetype\":0,\"gender\":0,\"mail\":\"\",\"markname\":\"\",\"nickname\":\"Half\",\"phonenumber\":\"\",\"signature\":\"\",\"status\":0,\"userid\":5,\"username\":\"15618326596\"},{\"address\":\"\",\"birthday\":19900101,\"clienttype\":0,\"customface\":\"\",\"facetype\":34,\"gender\":0,\"mail\":\"\",\"markname\":\"\",\"nickname\":\"云淡风轻\",\"phonenumber\":\"\",\"signature\":\"\",\"status\":0,\"userid\":7,\"username\":\"china001\"},{\"address\":\"上海市浦东新区南泉路1200号409室\",\"birthday\":20170914,\"clienttype\":0,\"customface\":\"\",\"facetype\":5,\"gender\":0,\"mail\":\"balloonwj@qq.com\",\"markname\":\"\",\"nickname\":\"qqq123\",\"phonenumber\":\"\",\"signature\":\"{“id”:12}\",\"status\":0,\"userid\":10,\"username\":\"qqq\"},{\"address\":\"\",\"birthday\":19900101,\"clienttype\":0,\"customface\":\"be19574dcdd11fb9a96cf00f7e5f0e66\",\"facetype\":0,\"gender\":0,\"mail\":\"\",\"markname\":\"\",\"nickname\":\"TzdnerC\",\"phonenumber\":\"\",\"signature\":\"\",\"status\":0,\"userid\":15,\"username\":\"TzdnerC\"},{\"address\":\"\",\"birthday\":19900101,\"clienttype\":0,\"customface\":\"\",\"facetype\":0,\"gender\":0,\"mail\":\"\",\"markname\":\"\",\"nickname\":\"Barry\",\"phonenumber\":\"\",\"signature\":\"\",\"status\":0,\"userid\":16,\"username\":\"17091203068\"},{\"address\":\"\",\"birthday\":19900101,\"clienttype\":0...太长了,这里省略...

让被 GDB 调试的程序接收信号

请看下面的代码:

void prog_exit(int signo)
{std::cout << "program recv signal [" << signo << "] to exit." << std::endl;
}int main(int argc, char* argv[])
{//设置信号处理signal(SIGCHLD, SIG_DFL);signal(SIGPIPE, SIG_IGN);signal(SIGINT, prog_exit);signal(SIGTERM, prog_exit);int ch;bool bdaemon = false;while ((ch = getopt(argc, argv, "d")) != -1){switch (ch){case 'd':bdaemon = true;break;}}if (bdaemon)daemon_run();//省略无关代码...}

在这个程序中,我们接收到 Ctrl + C 信号(对应信号 SIGINT)时会简单打印一行信息,而当用 GDB 调试这个程序时,由于 Ctrl + C 默认会被 GDB 接收到(让调试器中断下来),导致无法模拟程序接收这一信号。解决这个问题有两种方式:

  • 在 GDB 中使用 signal 函数手动给程序发送信号,这里就是 signal SIGINT;
  • 改变 GDB 信号处理的设置,通过 handle SIGINT nostop print 告诉 GDB 在接收到 SIGINT 时不要停止,并把该信号传递给调试目标程序 。
(gdb) handle SIGINT nostop print pass
SIGINT is used by the debugger.
Are you sure you want to change it? (y or n) y  Signal Stop Print Pass to program Description
SIGINT No Yes Yes Interrupt
(gdb)

函数明明存在,添加断点时却无效

有时候一个函数明明存在,并且我们的程序也存在调试符号,使用 break functionName 添加断点时 GDB 却提示:

Make breakpoint pending on future shared library load? y/n

即使输入 y 命令,添加的断点可能也不会被正确地触发,此时需要改变添加断点的方式,使用该函数所在的代码文件和行号添加断点就能达到效果。

第08课:GDB 实用调试技巧( 上)相关推荐

  1. C语言第二十课:实用调试技巧

    目录 前言: 一.Bug: 二.调试: 1.调试是什么: 2.调试的基本步骤: 3. Debug 与 Release : 三.在Windows环境下进行调试: 1.调试环境的准备: 2.调试的快捷键: ...

  2. C语言:实用调试技巧

    目录 C语言:实用调试技巧 1.什么是bug? 2.调试是什么?有多重要? 3.debug和release的介绍 4.Windows环境调试介绍 5.一些调试的实例 6.如何写出好(易于调试)的代码 ...

  3. C语言之实用调试技巧

    什么是bug? 调试是什么?有多重要? debug和release的介绍. windows环境调试介绍. 一些调试的实例. 如何写出好(易于调试)的代码. 编程常见的错误. 一. 什么是bug? 第一 ...

  4. VS2017实用调试技巧

    目录 历史上的第一个Bug,什么是bug 调试的重要性 现实中的你是会是这样子的吗? 调试的基本步骤 1.发现程序错误的存在 2.以隔离.消除等方式对错误进行定位 3.确定错误产生的原因 4.提出纠正 ...

  5. 实用调试技巧 Debug Release F10 F11 初始化 越界访问 堆栈 模拟实现库函数

    目录 一.什么是bug 二.调试是什么?有多重要? 1.调试 2.调试的基本步骤 三.Debug和Release 四.windows环境调试介绍 1.调试环境的准备 2.学会快捷键 Ctrl+U 改大 ...

  6. 验08利用gdb工具调试c语言程序,实验4_C开发工具和系统函数

    实验四C开发工具和系统函数 (一)C语言开发工具 目的 1.掌握gcc.make.gdb工具 2.熟悉c语言 内容 1.编写一个c语言程序:输出两行文字"Linux下的c也不是太难嘛!&qu ...

  7. ACM/OI中C++常用优化(实用/调试/技巧)代码(语法)

    一.C++万能编译头文件 #include<bits/stdc++.h> 从 #include <iostream> #include <cstdio> #incl ...

  8. C语言初阶——实用调试技巧

  9. 【C语言】实用调试技巧与const函数提升代码健壮性

    作者简介:大家好我是狂暴于涛侠

  10. 实用调试的技巧,VS编译器常用调试详解

    实用调试技巧 文章目录 实用调试技巧 什么是bug? 调试是什么?有多重要? Debug和Release的介绍 windows环境调试介绍 一些调试的实例 如何写出好的代码 const 什么是bug? ...

最新文章

  1. linux 系统调用 open函数使用
  2. XLNet团队:赢BERT靠的并不是数据集更大,公平对决也碾压对手
  3. centos7安装ftp_python 编译安装
  4. 【转】数据库的乐观锁和悲观锁
  5. 学习笔记(30):Python网络编程并发编程-Event事件
  6. Postgre体系结构图
  7. 当卷烟厂也那么卷后……
  8. [LeetCode][easy]Create Target Array
  9. hdu 5735 Born Slippy 暴力
  10. vue 开发app处理手机返回键问题
  11. 阿里云服务器大陆机房和香港机房如何选择?
  12. 新侨移民告诉你:为什么要移民新西兰?
  13. Verilog数码显示器00~99循环计数器电路
  14. 在自己的数据集上训练CrowdDet过程记录
  15. 什么是高度塌陷 以及高度塌陷的解决办法
  16. 杂项-公司:奇虎360
  17. python 数据挖掘 之 对数据进行简单预处理(1)
  18. android模拟器计算器,兔子计算器模拟器Wabbitem
  19. 用OpenZeppelin在RSK上进行以太坊ERC20代币开发
  20. C语言用pthread.h创建线程

热门文章

  1. 好玩的抖音、快手无水印视频下载工具
  2. 自动驾驶仿真:Carsim、NI和VTD联合仿真课题一
  3. 【信号与系统|吴大正】4:信号分解、傅里叶变换与信号谱(上)
  4. deepin 应用市场安装软件失败_深度商店软件无法安装问题解决方案
  5. 苹果cms V10模板 仿挖片自适应电影模板
  6. 用程序找出计算机c盘内容,电脑C盘空间空间清理方法
  7. 易语言_酷Q机器人插件_01
  8. hmcl手机版_hmcl启动器app下载
  9. hmcl手机版_hmcl启动器手机版下载-hmcl启动器官方正版下载v3.3.172-1y2y游戏
  10. 2022年四方系统/四方支付系统部署实战,以及细节讨论,Gitee版本