GDB抓虫之旅(上篇)
本文来自网易云社区。
作者:盛国存
前言
问: 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 0x400cc1
called by frame at 0x7fbffff910 source language c++.
Arglist at 0x7fbffff890, args: n=250
Locals at 0x7fbffff890, Previous frame's sp is 0x7fbffff8a0
Saved 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) //comment2
printf("线程1创建失败!\n"); else
printf("线程1被创建\n"); if((temp = pthread_create(&thread[1], NULL, thread2, NULL)) != 0) //comment3
printf("线程2创建失败"); else
printf("线程2被创建\n");
}void thread_wait(void)
{ /*等待线程结束*/
if(thread[0] !=0) { //comment4
pthread_join(thread[0],NULL); printf("线程1已经结束\n");
} if(thread[1] !=0) { //comment5
pthread_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+款云产品!
更多网易研发、产品、运营经验分享请访问网易云社区。
相关文章:
【推荐】 最小化局部边际的合并聚类算法(中篇)
【推荐】 网易美学-系统架构系列1-分布式与服务化
【推荐】 Android模拟器下载、编译及调试
GDB抓虫之旅(上篇)的更多相关文章
- 喜马拉雅FM抓包之旅
一.概述 最近学院组织安排大面积实习工作,今天刚刚发布了喜马拉雅FM实习生招聘的面试通知.通知要求:公司采用开放式题目的方式进行筛选,申请的同学须完成如下题目 写程序输出喜马拉雅FM上与"卓 ...
- Andorid自定义attr的各种坑
本文来自网易云社区 作者:孙有军 在开发Andorid应用程序中,经常会自定义View来实现各种各样炫酷的效果,在实现这吊炸天效果的同时,我们往往会定义很多attr属性,这样就可以在XML中配置我们想 ...
- 一篇文章看懂Facebook和新浪微博的智能FEED
本文来自网易云社区 作者:孙镍波 众所周知,新浪微博的首页动态流不像微信朋友圈是按照时间顺序排列的,而是按照一种所谓的"智能排序"的方式.这种违背了用户习惯的排序方式一直被用户骂, ...
- Spring Boot 学习系列(序)—Spring Boot
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. Spring Boot? Spring Boot 是由pivotal团队提供的一个基于Spring的全新框架 ...
- PHP(SentCMS)网站 “新手”捉虫记
我拖着疲惫的身躯,努力打开眼皮在写...... 昨晚弄到12点,我感觉应该弄好了. 故事开头是这样的:我呢朋友有个网站需要开发,我当时没时间就包给外面的公司了,由于外面公司维护费用比较贵. 那么网站维 ...
- PHPer 为什么会被 Javaer 鄙视?
最近看了知乎上的一个话题 「在工作中,为什么 Java 程序员常常瞧不起 PHP 程序员?」 个人从业多年,用过的后端语言 ASP.ASP.NET.Java.PHP.Node.js.Python,如果 ...
- iOS中的预编译指令的初步探究
目录 文件包含 #include #include_next #import 宏定义 #define #undef 条件编译 #if #else #endif #if define #ifdef #i ...
- iOS开发笔记--宏定义的黑魔法 - 宏菜鸟起飞手册
宏定义在C系开发中可以说占有举足轻重的作用.底层框架自不必说,为了编译优化和方便,以及跨平台能力,宏被大量使用,可以说底层开发离开define将寸步难行.而在更高层级进行开发时,我们会将更多的重心放在 ...
- 热爱工作 发财机会大增(这里不是选择软件还是硬件的问题,是自己的性格和追求的问题)——当你的老板不如你懂行的时候,还赚的盆满钵满的时候,你就可以考虑独立了 good
爱工作 发财机会大增 [ 油老板 ] 于:2011-02-09 06:39:41 复:1269077 认真回顾发主贴以来的三年半,俺觉得对于想发财的上班族来说,认真工作,刻苦钻研是发财的重要保证. 为 ...
随机推荐
- mybatis学习记录四——输入、输出映射
6 输入映射 通过parameterType指定输入参数的类型,类型可以是简单类型.hashmap.pojo的包装类型. 6.1.1 需求 完成用户信息的综合查询,需要传入查询条件很 ...
- mysql慢查询开启及分析方法
最近服务维护的公司的DB服务器,总是会出现问题,感觉需要优化一下了,登陆上去,发现慢查询日志都没有开,真是惭愧, 故果断加上慢查询日志, 经过分析sql记录,发现问题很多,开发人员很多没有对sql优化 ...
- Vue开发 localhost 替换成 本机ip无法访问
新版 vue-cli(@3.10.10) 构建的项目.localhost 替换成本机 ip 地址之后无法访问.但是替换成 127.0.0.1 可以访问 找到 config 文件夹下面的 index.i ...
- C#中rpt的数据类型和Oracle中数据类型的匹配
Oracle中number数据类型对应C#中decimal数据类型,结果是整数 Oracle中number数据类型对应C#中int32数据类型,结果是小数,保留两位小数 Oracle中中date类型数 ...
- Windows 2008 server + IIS 7 设置身份模拟(ASP.NET impersonation)
IIS7 与 IIS 6 相比有了很大的改动,原来在 IIS 6 下可以的设置到了 IIS 7 下有的会发生变化.身份模拟的配置上,IIS7 和 IIS6有很大不同,网上IIS6的身份模拟的文章比较多 ...
- c#数据库连接池Hikari重构升级
Hikari是我自定义的数据库连接池,前面已经提供了地址.因为c#的连接池按照规范的ADO.NET里面实现定义的.由数据库官方提供,但是实现方式就不知道了,反正没有看出来,估计一般是连接类实现的,但是 ...
- jquery mobile 移动web(6)
jquery mobile 针对移动端设备的事件类型. 1.touch 事件. tap 快速触摸屏幕并且离开,类似一种完整的点击操作. taphold 触摸屏幕并保持一段时间. swipe 在1秒内水 ...
- nodejs+express开发blog(2)
npm install -g nodemon 1,把ejs文件修改为html文件 app.engine('.html', require('ejs').__express);app.set('view ...
- IPC进程间通信---消息队列
消息队列 消息队列:消息队列是一个存放在内核中的消息链表,每个消息队列由消息队列标识符标识.与管道不同的是消息队 列存放在内核中,只有在内核重启(即操作系统重启)或者显式地删除一个消息队列时,该消息队 ...
- 03 shell编程之case语句与函数
本文所有内容均来自当年博主当年学习笔记,若有不足欢迎指正 Shell编程之case语句与函数 学习目标: 掌握case语句编程 掌握shell函数的使用 目录结构: Case语句 Case语句的作用 ...