第08课:GDB 实用调试技巧( 上)
本节课的核心内容:
- 将 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 实用调试技巧( 上)的更多相关文章
- 第09课:GDB 实用调试技巧(下)
本节课的核心内容: 多线程下禁止线程切换 条件断点 使用 GDB 调试多进程程序 多线程下禁止线程切换 假设现在有 5 个线程,除了主线程,工作线程都是下面这样的一个函数: void thread_p ...
- Chrome 实用调试技巧
Chrome 实用调试技巧 2016-07-23 如今Chrome浏览器无疑是最受前端青睐的工具,原因除了界面简洁.大量的应用插件,良好的代码规范支持.强大的V8解释器之外,还因为Chrome开发者工 ...
- gdb命令调试技巧
gdb命令调试技巧 一.信息显示1.显示gdb版本 (gdb) show version2.显示gdb版权 (gdb) show version or show warranty3.启动时不显示提示信 ...
- Chrome实用调试技巧
如今Chrome浏览器无疑是最受前端青睐的工具,原因除了界面简洁.大量的应用插件,良好的代码规范支持.强大的V8解释器之外,还因为Chrome开发者工具提供了大量的便捷功能,方便我们前端调试代码,我们 ...
- Android Studio 实用调试技巧
Android Studio 是个发工具,其自身带调式环境是很强大的,我们要摆脱只会使用Log打印日志的低效的方法,掌握高级调试技巧对每个Android开发者都是很必要的,废话少说,直入正题 调试方式 ...
- VS2010中的调试技巧
作者: scottgu 这是我的博客中关于VS 2010和.NET 4发布系列的第二十六篇文章. 今天的博文将介绍Visual Studio中的一些实用调试技巧.这是受我朋友Scott Cate (他 ...
- Javascript调试技巧整理
整理一下网上看到的实用调试技巧! 1. 不要使用alert 首先,alert只能打印出字符串,如果打印的对象不是String,则会调用toString()方法将该对象转成字符串(比如转成[object ...
- gdb各种调试命令和技巧
陈皓:用GDB调试程序 GDB概述———— GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具.或许,各位比较喜欢那种图形界面方式的,像VC.BCB等IDE的调试,但如果你是在UNIX平台 ...
- pwn 题GDB调试技巧和exp模板
GDB分析ELF文件常用的调试技巧 gdb常用命令 首先是gbd+文件名 静态调试 ,gdb attach +文件名 动态调试 为了方便查看堆栈和寄存器 最好是安装peda插件 安装 可以通过pip直 ...
随机推荐
- NCB | 定量蛋白质组学揭示细胞外泌体通用标志物Syntenin-1
外泌体 (exosomes) 是由哺乳动物细胞通过"内吞-融合-外排"等机制,主动向胞外释放的纳米级 (直径40~60 nm) 双层囊泡小体,携带蛋白质.核酸.脂质等多种生物活性分 ...
- Nmap的多进程应用与研究
Nmap的多进程应用 使用Nmap进行多目标多端口(强调端口数目较多,比如全端口)扫描时,其在执行时间上的表现并不好.本文旨在分析多目标多端口扫描时的速度瓶颈以及减少时间成本的解决方案. 实验 实验环 ...
- MySQL Schema 与数据类型优化
良好的逻辑设计和物理设计是高性能的基石,应该根据系统将要执行的查询语句来设计schema,这往往需要权衡各种因素. 例如,反范式的设计可以加快某些类型的查询,但同时可能使另一些类型的查询变慢:添加计数 ...
- 如何将代码优雅的插入到word中
介:写博客或者word时需要插入代码,但如何更优雅的将代码插入到word中呢? 反面教材如下: 技巧步骤1:插入表格,设置表格无边框: 技巧步骤2:使用Notepad++的高级功能: 大部分代码编辑器 ...
- Create Virtual Network with VirtualBox on Mint 14
VirtualBox version: VirtualBox-4.2.18-88780-Linux_x86.run Host OS: Linux Mint 14 Xfce Setup Network ...
- Java:导出Excel大批量数据的优化过程
背景 团队目前在做一个用户数据看板(下面简称看板),基本覆盖用户的所有行为数据,并生成分析报表,用户行为由多个数据来源组成(餐饮.生活日用.充值消费.交通出行.通讯物流.交通出行.医疗保健.住房物业. ...
- SpringMVC/boot-CSRF安全方案
1. CSRF原理与防御方案概述 一. 原理 增删改的接口参数值都有规律可循,可以被人恶意构造增删改接口 将恶意构造的增删改接口发给对应特定用户,让特定用户点击 特定用户使用自己的认证信息对该接口发起 ...
- BeautifulSoup4的使用
一.介绍 Beautiful Soup 主要是用来解析提取 HTML 和 XML 文件中的数据. 现在官网推荐使用 Beautiful Soup 4 ,已经被移植到了BS4中. 安装 Beautifu ...
- Angular Module 共享模块使用 父模块使用多个子模块
Component.module.ts import {BrowserModule} from '@angular/platform-browser'; import {LocationStrat ...
- MySQL:互联网公司常用分库分表方案汇总!
转载别人 一.数据库瓶颈 不管是IO瓶颈,还是CPU瓶颈,最终都会导致数据库的活跃连接数增加,进而逼近甚至达到数据库可承载活跃连接数的阈值.在业务Service来看就是,可用数据库连接少甚至无连接可用 ...