范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

GDB调试的高级技巧

  GDB是我们平时调试c/c++程序的利器, 查起复杂的bug问题,比打印大法要好得多,但是也不得不说, gdb在默认情况下用起来并不是很好用,最近学习到几个高级点的技巧,分享下: 一 美化打印
  先上个例子: #include   typedef struct {  int i ;  int j;  char * str;  int array[10]; } test_type_t;  int main (int argc, char * argv[]) {   test_type_t t = {1,2,"test a str" ,{1,2,3,4,5,6,7,8,9,10}};   printf("i:%d,j:%d ", t.i,t.j);   return 0; }
  gdb调试: (gdb) n 14   printf("i:%d,j:%d ", t.i,t.j); (gdb) p t $1 = {i = 1, j = 2, str = 0x400710 "test a str", array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}} (gdb) set print pretty (gdb) p t $2 = {   i = 1,    j = 2,    str = 0x400710 "test a str",    array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} } (gdb)
  set print pretty  通过这个命令可以美化gdb的打印,特别是复杂的数据结构,比较推荐.  set print array-indexes on  打印数组的下标
  这些命令如果记不住怎么办, 类似linux启动,会执行些初始化脚本,gdb也一样,脚本名为:  .gdbinit 将刚才的两个命令加入进去,就不用每次执行这个命令调试.二 动态打印
  一般情况下,我们用gdb调试的时候,先在产生问题的代码的调用逻辑链上设置端点,调试,有时候为了更方便调试,我们会在这些关键地方加上打印语句. 有时候加的打印代码不够全,来回要反复几次. 每次加好打印代码后,需要编译程序,来回折腾几次,确实比较麻烦.
  GDB提供动态打印功能,可以在不修改代码情况下,动态插入打印语句,说的比较抽象,举例说明:   2 #include    3    4 typedef struct {   5  int i ;   6  int j;   7  char * str;   8  int array[10];   9 } test_type_t;  10   11 int main (int argc, char * argv[])  12 {  13   test_type_t t = {1,2,"test a str" ,{1,2,3,4,5,6,7,8,9,10}};  14   printf("i:%d,j:%d ", t.i,t.j);  15   16   for (int k = 0; k <= 10; k++ ) {  17       t.array[k] += 10;  18   }  19   printf("index 0 :%d" ,t.array[0]);  20   return 0;  21 }
  上面位置 k <= 10;  这一行越界,调试下:(gdb) dprintf 17,"k:%d,array[k]:%d ",k,t.array[k] Dprintf 2 at 0x40067f: file 1.c, line 17. (gdb) r Starting program: /test/a.out   Breakpoint 1, main (argc=1, argv=0x7fffffffe648) at 1.c:13 13   test_type_t t = {1,2,"test a str" ,{1,2,3,4,5,6,7,8,9,10}}; Missing separate debuginfos, use: debuginfo-install glibc-2.17-196.el7_4.2.x86_64 libgcc-4.8.5-16.el7_4.2.x86_64 libstdc++-4.8.5-16.el7_4.2.x86_64 (gdb) c Continuing. i:1,j:2 k:0,array[k]:1 k:1,array[k]:2 k:2,array[k]:3 k:3,array[k]:4 k:4,array[k]:5 k:5,array[k]:6 k:6,array[k]:7 k:7,array[k]:8 k:8,array[k]:9 k:9,array[k]:10 k:10,array[k]:0 index 0 :11[Inferior 1 (process 150109) exited normally] (gdb) info b Num     Type           Disp Enb Address            What 1       breakpoint     keep y   0x00000000004005fc in main(int, char**) at 1.c:13  breakpoint already hit 1 time 2       dprintf        keep y   0x000000000040067f in main(int, char**) at 1.c:17  breakpoint already hit 11 times         printf "k:%d,array[k]:%d ",k,t.array[k]
  我们通过 dprintf 17,"k:%d,array[k]:%d ",k,t.array[k]  在17行动态插入打印语句,然后执行的时候会直接打印出来,17 为行号,后面的语法类似printf.
  动态的语句实际是一个断点(通过info b 可以看到),只不过这个断点会自动的恢复,这种动态语句是否可以继续在上面设置端点的,答案是不行的,通过next执行的时候也执行不到这个语句,只是运行到这里面的时候,可以自动打印变量. 三 断点信息的保存和加载
  调试大型程序的时候,往往会设置很多断点,如果需要多次调试,来回敲这些断点信息,也是很烦的,可以通过 save breakpoints filename 的方法,将断点设置信息保存到filename 文件中,GDB启动后,在通过source filename 方式加载:(gdb) save breakpoints break.bp Saved to file "break.bp". (gdb) quit [root@localhost test]# ls 1.c  a.out  break.bp [root@localhost test]# cat break.bp  break main dprintf  /test/1.c:17,"k:%d,array[k]:%d ",k,t.array[k]
  加载: [root@localhost test]# gdb ./a.out  Reading symbols from /test/a.out...done. (gdb) source break.bp Breakpoint 1 at 0x4005fc: file 1.c, line 13. Dprintf 2 at 0x40067f: file 1.c, line 17. (gdb) info b Num     Type           Disp Enb Address            What 1       breakpoint     keep y   0x00000000004005fc in main(int, char**) at 1.c:13 2       dprintf        keep y   0x000000000040067f in main(int, char**) at 1.c:17         printf "k:%d,array[k]:%d ",k,t.array[k]
  是不是很方便那. 四 宏打印
  如下示例代码:  1 #include    2    3 #define MAX(x,y) (x)>=(y)?(x):(y)   4    5 int main(int argc , char * argv[])   6 {   7     char * p = (char*)0x12345;   8     printf("max(3,5):%d ",MAX(3,5));   9     printf("print a test str ");  10     *p = 1;  11     printf("end ");  12 }
  如果通过 -g 选项编译是无法查看宏定义的,可以通过-g3  编译,就可以轻松查看宏定义和宏展开了,如下:[root@localhost test]# gdb ./2 Reading symbols from /test/2...done. (gdb) b main Breakpoint 1 at 0x40064c: file 2.c, line 7. (gdb) r Starting program: /test/./2   Breakpoint 1, main (argc=1, argv=0x7fffffffe648) at 2.c:7 7     char * p = (char*)0x12345; Missing separate debuginfos, use: debuginfo-install glibc-2.17-196.el7_4.2.x86_64 libgcc-4.8.5-16.el7_4.2.x86_64 libstdc++-4.8.5-16.el7_4.2.x86_64 (gdb) n 8     printf("max(3,5):%d ",MAX(3,5)); (gdb) p MAX(3,5) $1 = 5 (gdb) macro expand MAX(3,5) expands to: (3)>=(5)?(3):(5)
  可以直接通过p命令打印宏,也可以进行 macro expand MAX(3,5) 宏展开,调试宏的时候比较有用.五 gdb调试界面
  gdb的调试一般是通过n执行下一条命令,然后通过l查看当前的代码,不够直观,gdb其实也可以类似IDE那样,显示一行行代码执行,简单的直接输入 layout  切换布局:
  再输入n的时候,箭头自动下移一行.
  更棒的是可以同时显示源码和汇编,输入 layout split
  六 Debug汇编
  有时候,比较麻烦的bug,可以需要反编译为汇编(disassemble /m main),然后调试, 还是如上的例子程序,调试如下,汇编模式常需要看寄存器的值,输入 layout regs 可以同时展示汇编和寄存器的值:
  这个模式下好处,可以通过n命令执行一条条看汇编指令.
  我还是更喜欢用以下的方式调试: gdb) disassemble /m main Dump of assembler code for function main(int, char**): 6 {    0x000000000040063d <+0>: push   %rbp    0x000000000040063e <+1>: mov    %rsp,%rbp    0x0000000000400641 <+4>: sub    $0x20,%rsp    0x0000000000400645 <+8>: mov    %edi,-0x14(%rbp)    0x0000000000400648 <+11>: mov    %rsi,-0x20(%rbp)  7     char * p = (char*)0x12345; => 0x000000000040064c <+15>: movq   $0x12345,-0x8(%rbp)  8     printf("max(3,5):%d ",MAX(3,5));    0x0000000000400654 <+23>: mov    $0x5,%esi    0x0000000000400659 <+28>: mov    $0x400720,%edi    0x000000000040065e <+33>: mov    $0x0,%eax    0x0000000000400663 <+38>: callq  0x400510   9     printf("print a test str ");    0x0000000000400668 <+43>: mov    $0x40072d,%edi    0x000000000040066d <+48>: callq  0x400530   10     *p = 1;    0x0000000000400672 <+53>: mov    -0x8(%rbp),%rax    0x0000000000400676 <+57>: movb   $0x1,(%rax)  11     printf("end ");    0x0000000000400679 <+60>: mov    $0x40073e,%edi    0x000000000040067e <+65>: callq  0x400530   12 }    0x0000000000400683 <+70>: mov    $0x0,%eax    0x0000000000400688 <+75>: leaveq     0x0000000000400689 <+76>: retq     End of assembler dump. (gdb) ni 8     printf("max(3,5):%d ",MAX(3,5)); (gdb) ni 0x0000000000400659 8     printf("max(3,5):%d ",MAX(3,5)); (gdb) ni 0x000000000040065e 8     printf("max(3,5):%d ",MAX(3,5)); (gdb) ni 0x0000000000400663 8     printf("max(3,5):%d ",MAX(3,5)); (gdb) ni max(3,5):5 9     printf("print a test str "); (gdb) ni 0x000000000040066d 9     printf("print a test str "); (gdb) ni print a test str 10     *p = 1; (gdb) info register
  通过 disassemble /m main  将源码和汇编一起显示,ni  执行下一条汇编指令. info register 来显示汇编信息,core的位置的指令为: 0x0000000000400676 <+57>: movb $0x1,(%rax)  将1赋值给rax寄存器保存的地址, 我们可以看下rax寄存器,p $rax  直接打印,然后通过x /x 0x12345  来测试下这个地址是否合法,这个地址不是栈的地址,也不是我们申请的堆地址,直接写,就引起的段错误.七 诗词欣赏# 滚滚长江东逝水,浪花淘尽英雄。  出自明代[杨慎]   滚滚长江东逝水,浪花淘尽英雄。 是非成败转头空。青山依旧在,几度夕阳红。 白发渔樵江渚上,惯看秋月春风。 一壶浊酒喜相逢。古今多少事,都付笑谈中。

显卡降价频率加快什么时候能买到平价显卡?央广网北京3月25日消息(记者吕红桥)据中央广播电视总台经济之声天下财经报道,今年以来,显卡价格持续回落。记者从一些电子设备经销商处了解到,有些显卡最近一天一个价,降价频率还在加快为什么大家更倾向于买红米K50而不是K50Pro?红米K50的销量几倍于红米K50Pro,价格只是一方面,应该更多用户觉得K50的性价比更高!先来了解一下红米K50Pro都有哪些升级1处理器红米K50Pro升级到天玑9000,极限魅族19X再续辉煌,天玑9000撑腰,首搭161TB大存储曾几何时,魅族也和小米华为一样坐拥无数忠实粉丝,尤其是FiymeOS很受广大用户好评,使用体验不比苹果iOS差。但后来由于种种原因,魅族沦为不知名的小众品牌,在智能手机的影响力还不智慧自集尘支持鸿蒙智联的清易H40PLUS扫拖机器人扫拖机器人这两年发展很快,除了常规的扫地拖地路径规划等功能上的升级,一线大厂都开始发力自动集尘。在解放双手这件事上,自动集尘功能我觉得是很重要的一块拼图。因为日常使用,无论尘盒设计小影夫妇为更好地服务顾客,自建云仓1997年,我国互联网出现了最早的两家电子商务公司中国商品交易中心和中国化工网分别上线,B2B业务逐渐开始得到发展。1999年,我国第一家C2C电商8848正式成立。同年8月,易趣微软面经记我的微软8面经历本文来自用户Accelete(站内排名346)分享,可进入力扣社区与他互动喔!背景985本科,工作一年半,微软社招base苏州。因为我的技术栈偏向前端,所以面试中的部分问题也跟前端亏损收窄至40亿元整车毛利率超20,蔚来预计这年实现盈利2021年是充满挑战的一年。3月25日,蔚来发布的财报数据显示,2021年全年蔚来营收为361。4亿元,同比增长122。3,其中汽车销售收入331。69亿元,同比增长118。5全年贝佐斯前妻再捐38。6亿美元总计已捐125亿亚马逊创始人贝佐斯的前妻麦肯齐斯科特周三公布了又一轮捐赠,自去年6月以来向465个非营利组织总计捐赠了38。6亿美元。这使她迄今为止的捐赠总额达到125亿美元。斯科特在一篇最新博客广汽三菱首款纯电SUV阿图柯上市,日系车企加速电动化转型每经记者孙桐桐每经编辑孙磊日前,广汽三菱首款纯电动SUV阿图柯(AIRTREK)正式上市,新车共推出先锋版和硬核版两款车型,售价分别为19。98万元和22。98万元。据了解,阿图柯iQOO10Pro展露锋芒,18G大运存110万高跑分,定为5999够意思近年来,vivo确实给国人带来了不小的惊喜,除硬核实力大幅提升之外,还抢占了不少的市场份额,连续好几个季度稳居国内市场第一。可vivo能有这样华丽的成绩,子品牌iQOO也是一大功臣OPPO再次帮一加覆盖线下渠道,承认自己是子品牌?相信曾经一加手机闭店的消息大家还历历在目,2015年关闭45家专卖店的消息你现在还能搜到,从那之后线下渠道就没怎么拓展。而最近宣布覆盖渠道则有些意味深长,宣布进入2800个县城这个
Go语言常见面试题汇总解析!(2021PDF新版)Go语言诞生于google,作为编程语言的后起之秀,在语言层面具有语法简洁执行效率高等特点,Go语言瞄准大数据云计算时代背景下的高并发和分布式应用场景,可以说是为并发而生的。Go语HTTP竟然如此通俗易懂,万次长文解析HTTP相关知识!拿来吧你绝大多数的Web应用都是基于HTTP来进行开发的。我们对Web的操作都是通过HTTP协议来进行传输数据的。简单来说,HTTP协议就是客户端和服务器交互的一种通迅的格式。HTTP的诞马哥亲授173页Docker学习笔记,从基础到进阶Docker是使用Go语言进行开发实现的,Docker自开源后受到广泛的关注和讨论,跟传统的虚拟化方式相比有更高效的利用系统资源更快速的启动时间一致的运行环境持续交付和部署更轻松的linux下文本处理三剑客学习汇总grepsedawkgrep命令主要对文本的(正则表达式)行基于模式进行过滤sedstreameditor,文本编辑工具awkLinux上的实现gawk,文本报告生成器文本处理三剑客之grepgrepLinux基础文本处理三剑客之sed学习笔记本文内容Sed介绍Sed用法Sed高级用法处理文本的工具sedStreamEDitor,行编辑器sed是一种流编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,计算机基础知识超强总结!马哥教育出品计算机系统计算机系统由硬件(Hardware)系统和软件(Software)系统两大部分组成计算机硬件计算机(Computer)俗称电脑,是一种能接收和存储信息,并按照存储在其内部方大同算不算Blues?TANCHJIMBlues林氏评测我对blues这个曲风,犹如对川菜一样,一直以来,都是一知半解的。在大多数人来印象里,川菜代表着什么?是火锅?是想起来就觉得菊花残?还是开遍各地的成都小吃?然而住在成都已逾四年的我开学开学开学开学(请悄悄点进来)有人很害怕开学么?当年的我,可是巴不得赶紧开学的!暑假太长了,长到令人发指,家里呆半个月就该腻了吧?虽然不用上课虽然家附近也有小伙伴,然而几点外出几点回来基本都要守规矩,作为一个打黄金白银圣斗士?闲叙AP80黄铜版ampampamp不锈钢版换壳会导致音质不同?这件事情可能有些人听起来会觉得略为玄学,但实际上,这是很科学的。由于不同金属材质在导电导磁性能屏蔽效能方面存在先天的物理差异,故而就算一台机器的内部架构用料完全AKG回来了?新品N700NCN200NC在京发布2019年8月3号,主题为时光走廊的AKG新品品鉴会在京举行。AKG总代理北京恒远恒信科技发展有限公司相关领导,以及在场的数十家媒体共同见证了AKG新品蓝牙无线降噪耳机N200NC方大同算不算Blues?TANCHJIMBlues林氏评测我对blues这个曲风,犹如对川菜一样,一直以来,都是一知半解的。在大多数人来印象里,川菜代表着什么?是火锅?是想起来就觉得菊花残?还是开遍各地的成都小吃?然而住在成都已逾四年的我