本文来自网易云社区。

作者:盛国存

前言

问: gdb是什么?
答: 强大的UNIX下命令行调试工具。问: gdb能干什么?
答: 让你随心所欲的驾驭你的程序;Start、Stop、Examine、Change。问: 我们为什么要学习gdb?
答: 欲善其事,必先利其器;利用gdb进一步的定位程序异常。问: 本次分享的宗旨?
答: gdb的介绍和使用入门,为大家抓虫多提供一个选择。

抓虫从0开始

前期准备

1.包含有调试信息的可执行文件

2.编译时加-g选项即可,不建议开优化选项

GDB的启动

gdb <program>gdb <program> coregdb <program> <PID>
(gdb) file <program>

抓虫流程

实战1 :  GDB基础命令的使用

1.1、示例程序(example_1.cpp)

#include <iostream>#include <string>using namespace std;int foo(int m, int n){    return 1;
}int foo(int n){    int result=0;    for (int i=0;i<=n;i++){result+=n;}    return result;
}int main(){    string s1="dafdf";    char * s2;//  s1=s2;int sum =0;    for (int i=1;i<=100;i++){sum+=i;}cout<<"result[1-100]="<<sum<<endl;cout<<"result[1-250]="<<foo(250)<<endl;    return 0;
}

1.2、调试准备 编译命令:g++ -g -Wall -o example_1 example_1.cpp

1.3、启动gdb

$ gdb example_1
GNU gdb Red Hat Linux (6.3.0.0-1.96rh)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu"...Using host libthread_db library "/lib64/tls/libthread_db.so.1".

1.4、辅助性命令

(gdb) cd ..
Working directory /home/work/testers/sgc.
(gdb) shell ls
autotest  client  Makefile  spanti  spantispam_if.h  study(gdb) cd study/
Working directory /home/work/testers/sgc/study.
(gdb) pwd
Working directory /home/work/testers/sgc/study.
(gdb) help run
Start debugged program.  You may specify arguments to give it.
Args may include "*", or "[...]"; they are expanded using "sh".
Input and output redirection with ">", "<", or ">>" are also allowed.With no arguments, uses arguments last specified (with "run" or "set args").
To cancel previous arguments and run with no arguments,use "set args" without arguments.

1.5、设置断点命令

//查看源代码信息(gdb) l17                      result+=n;18              }19              return result;2021      }2223      int main()24      {2526              string s1="dafdf";
(gdb) l 11       #include <iostream>2       #include <string>345       using namespace std;6       int foo(int m, int n)7       {89               return 1;10(gdb) l example_1.cpp:1611      }12      int foo(int n)13      {14              int result=0;15              for (int i=0;i<=n;i++)16              {17                      result+=n;18              }19              return result;20(gdb) l foo(int)8
9               return 1;1011      }12      int foo(int n)13      {14              int result=0;15              for (int i=0;i<=n;i++)16              {17                      result+=n;
//设置断点(gdb) b 17Breakpoint 1 at 0x400c07: file example_1.cpp, line 17.(gdb) b main
Breakpoint 2 at 0x400c27: file example_1.cpp, line 26.(gdb) info br
Num Type           Disp Enb Address            What1   breakpoint     keep y   0x0000000000400c07 in foo(int) at example_1.cpp:17
2   breakpoint     keep y   0x0000000000400c27 in main at example_1.cpp:26

1.6、执行控制命令

(gdb) r
Starting program: /home/work/testers/sgc/study/example_1 Breakpoint 2, main () at example_1.cpp:2626              string s1="dafdf";
(gdb) c
Continuing.
result[1-100]=5050Breakpoint 1, foo (n=250) at example_1.cpp:1717                      result+=n;
(gdb) n
15              for (int i=0;i<=n;i++)

1.7、程序信息查看命令

//查看变量信息
(gdb) p result$1 = 250(gdb) p s1$2 = 1431655765(gdb) disp result1: result = 250(gdb) c
Continuing.Breakpoint 1, foo (n=250) at example_1.cpp:1717                      result+=n;1: result = 250(gdb) info locals
i = 1result = 250//查看栈信息
(gdb) bt#0  foo (n=250) at example_1.cpp:17#1  0x0000000000400cc1 in main () at example_1.cpp:38(gdb) info f
Stack level 0, frame at 0x7fbffff8a0:rip = 0x400c07 in foo(int) (example_1.cpp:17); saved rip 0x400cc1called by frame at 0x7fbffff910 source language c++.Arglist at 0x7fbffff890, args: n=250Locals at 0x7fbffff890, Previous frame's sp is 0x7fbffff8a0Saved registers:rbp at 0x7fbffff890, rip at 0x7fbffff898
(gdb) f 0
#0  foo (n=250) at example_1.cpp:17
17                      result+=n;

1.8、修改环境命令

(gdb) set var i=97(gdb) p i
$5 = 97(gdb) print i=98$6 = 98(gdb) ignore 1 300Will ignore next 300 crossings of breakpoint 1.(gdb) finish
Run till exit from #0  foo (n=250) at example_1.cpp:170x0000000000400cc1 in main () at example_1.cpp:3838              cout<<"result[1-250]="<<foo(250)<<endl;Value returned is $8 = 38500
(gdb) quit
The program is running.  Exit anyway? (y or n) y

不要放过core文件

问 :Core文件是什么?
答 :a disk file containing an image of the process's memory at the time of termination

问 :Core的作用?
答 :
  1、让你在调试时,不用花费大量等待程序出错;
  2、让你避免了单步调试的烦恼
  3、让你定位错误所在

启动方式

$ gdb <program> core

查看程序信息的常用命令

1、查看栈信息:bt, f n, up/down,info frame

2、查看变量信息:info args|locals

实战2 :  core文件调试

2.1、示例程序(crash2.c)

#include <string.h>void Strcpy(char *to , char *from){strcpy(to , from);
}int main(){    char *s = NULL;Strcpy(s, "abcdefg");    return 0;
}

2.2、查看信息

$ gdb ./crash2 core.19562 GNU gdb Red Hat Linux (6.3.0.0-1.96rh)Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu"...Using host libthread_db library "/lib64/tls/libthread_db.so.1".Core was generated by `./crash2'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib64/tls/libc.so.6...done.
Loaded symbols for /lib64/tls/libc.so.6
Reading symbols from /lib64/ld-linux-x86-64.so.2...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
#0  0x000000302af6f9a4 in strcpy () from /lib64/tls/libc.so.6(gdb) bt
#0  0x000000302af6f9a4 in strcpy () from /lib64/tls/libc.so.6
#1  0x00000000004004c5 in Strcpy (to=0x0, from=0x4005dc "abcdefg") at crash2.c:5
#2  0x00000000004004e5 in main () at crash2.c:10(gdb) f 0
#0  0x000000302af6f9a4 in strcpy () from /lib64/tls/libc.so.6(gdb) up
#1  0x00000000004004c5 in Strcpy (to=0x0, from=0x4005dc "abcdefg") at crash2.c:5
5                       strcpy(to , from);
(gdb) info args
to = 0x0from = 0x4005dc "abcdefg"//至此,已经清楚的发现了问题所在,to指针为空

进阶之多线程程序调试

多线程调试常用命令

$ info <...>  // 强大的查看命令,如info threads
$ attach/detach <pid> // 挂载到进程
$ thread <thread_no> // 切换到线程
$ thread apply <thread_no_list> <cmd>// 对于list中的thread,执行cmd
$ break <linenum> thread <threadno> if ...

实战3 :  多线程程序调试

3.1、正常的示例程序(good_thread.c)

#include <pthread.h>#include <stdio.h>#include <sys/time.h>#include <string.h>#define MAX 10pthread_t thread[2];
pthread_mutex_t mut;int number=0, i;void *thread1()
{        printf ("thread1 : I'm thread 1\n");        for (i = 0; i < MAX; i++){                printf("thread1 : number = %d\n",number);pthread_mutex_lock(&mut);number++;pthread_mutex_unlock(&mut);sleep(2);}        printf("thread1 :主函数在等我完成任务吗?\n");pthread_exit(NULL);
}void *thread2()
{        printf("thread2 : I'm thread 2\n");        for (i = 0; i < MAX; i++){                printf("thread2 : number = %d\n",number);pthread_mutex_lock(&mut);number++;pthread_mutex_unlock(&mut);sleep(3);}        printf("thread2 :主函数在等我完成任务吗?\n");pthread_exit(NULL);
}void thread_create(void)
{        int temp;        memset(&thread, 0, sizeof(thread));          //comment1/*创建线程*/if((temp = pthread_create(&thread[0], NULL, thread1, NULL)) != 0)       //comment2printf("线程1创建失败!\n");        elseprintf("线程1被创建\n");        if((temp = pthread_create(&thread[1], NULL, thread2, NULL)) != 0) //comment3printf("线程2创建失败");        elseprintf("线程2被创建\n");
}void thread_wait(void)
{        /*等待线程结束*/if(thread[0] !=0) {                   //comment4pthread_join(thread[0],NULL);                printf("线程1已经结束\n");}        if(thread[1] !=0) {                //comment5pthread_join(thread[1],NULL);                printf("线程2已经结束\n");}
}int main()
{        /*用默认属性初始化互斥锁*/pthread_mutex_init(&mut,NULL);        printf("我是主函数哦,我正在创建线程,呵呵\n");thread_create();        printf("我是主函数哦,我正在等待线程完成任务阿,呵呵\n");thread_wait();        return 0;
}

网易云免费体验馆,0成本体验20+款云产品!

更多网易研发、产品、运营经验分享请访问网易云社区。

相关文章:
【推荐】 最小化局部边际的合并聚类算法(上篇)

GDB抓虫之旅(上篇)相关推荐

  1. 不让Bug陪你过年,StarRocks年终抓虫派对重金相邀!

    在 2022 年即将结束之际,StarRocks 社区决定广发邀请函,邀请各路抓虫达人,一起帮助 StarRocks 在稳定性上更上一层楼.我们也将送出价值上万的京东购物卡.社区周边等多项好礼作为报答 ...

  2. 喜马拉雅FM抓包之旅

    一.概述 最近学院组织安排大面积实习工作,今天刚刚发布了喜马拉雅FM实习生招聘的面试通知.通知要求:公司采用开放式题目的方式进行筛选,申请的同学须完成如下题目 写程序输出喜马拉雅FM上与"卓 ...

  3. python抓虫_python抓取糗事百科并保存文件的小虫虫代码

    本帖最后由 ivenzlzhang 于 2018-8-21 14:13 编辑 本人python小白,近一个月在学习python编程,发现python强大的第三方库简直是小白的福音. 因此把学习用的知识 ...

  4. 官方抓虫,PyTorch 新版本修复 13 项 Bug

    整理 | 寇雪芹 头图 | 下载于视觉中国 出品 | AI科技大本营(ID:rgznai100) 近日,PyTorch 发布了新版本 PyTorch 1.8.1,相比3月4日从 PyTorch 1.7 ...

  5. python抓虫_Python 七步捉虫法

    了解一些技巧助你减少代码查错时间. 在周五的下午三点钟(为什么是这个时间?因为事情总会在周五下午三点钟发生),你收到一条通知,客户发现你的软件出现一个错误.在有了初步的怀疑后,你联系运维,查看你的软件 ...

  6. 抓虫系列(三) 不要轻视web程序中常用的三个池 之数据库连接池

    前篇回顾:应用程序池在项目中引发的问题不多,不过如果遇到了没有经历过的话可能会比较茫然,呵呵.当然重点还是数据库连接池与线程池了. 本篇虫子就结合demo程序给大家演示下数据库连接池会给大家的程序带来 ...

  7. 抓虫记之七:模拟鼠标移动就报错

    有时候显示的BUG,你可能看不懂.有时候显示的BUG,你想不通. 下面这个案例,当时遇到的时候就非常想不通.我们产品将于GTF(公司的自动化测试框架),做了自动化测试.测试人员发现,在模拟绘制模型的时 ...

  8. Andorid自定义attr的各种坑

    本文来自网易云社区 作者:孙有军 在开发Andorid应用程序中,经常会自定义View来实现各种各样炫酷的效果,在实现这吊炸天效果的同时,我们往往会定义很多attr属性,这样就可以在XML中配置我们想 ...

  9. 网易云易盾牵手百视通 助力广电领域新媒体内容安全

    经过严格的遴选,国内领先的智能内容安全服务商网易云易盾脱颖而出成为百视通BesTV App合作伙伴,携手百视通共同构建纯净健康的内容生态. 百事通是中国大陆首家获得IPTV运营牌照的公司,依托上海文化 ...

最新文章

  1. git 忽略指定文件夹的上传
  2. Fast and accurate short read alignment with Burrows-Wheeler transform
  3. 在INSTALL TINY时出现下面的问题怎么办?
  4. 水滴石穿C语言之extern声明辨析
  5. 微软7月修复117个漏洞,其中9个为0day,2个是Pwn2Own 漏洞
  6. android中颜色对应的值
  7. 安卓开发和python哪个难_入门IT该学Java还是Python?看完这篇你就懂了
  8. Linux - 虚拟网络设备- TUN,TAP,ip tunnel
  9. 标准工时分析怎么做?精益生产下的VIOOVI 标准工时分析软件
  10. webstorm破解
  11. Windows 11旗舰版
  12. JS代码计算正方教务系统目前成绩的加权平均分和平均绩点
  13. ie主页被劫持怎么办 解决浏览器主页劫持方法
  14. 云学python (第二章用编程改造世界·小练习)《vamei-从Python开始学编程》
  15. webpack serve 配置问题TypeError: Class constructor ServeCommand cannot be invoked without ‘new‘
  16. 我的一些杭电计算机考研资料
  17. html5与ccs网页制作,HTML5CCS3(1) 网页的构造块
  18. FreeRTOS-ARM架构深入理解
  19. python文件转换成C文件
  20. JAVA前端与后端参数传递方法小结

热门文章

  1. win7程序关闭后弹出 程序兼容性助手 这个程序可能安装不正确 如果此程序没有正确安装,处理方式...
  2. C#:获取随机昵称实现
  3. Eclipse插件开发调试
  4. centos下卸载jdk
  5. 2018上海交大计算机学院,2018年上海交大毕业生,都去哪里了?看这张图就知道![图]...
  6. wireshark数据包修改--IP地址修改(一)
  7. 一些电脑使用问题:电脑桌面图标变白
  8. 深入理解JVM之垃圾回收算法
  9. devops实践-开篇感想
  10. ucore lab 2