前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Biu一下GDB

Biu一下GDB

作者头像
Cloud-Cloudys
发布2020-07-06 11:34:31
3210
发布2020-07-06 11:34:31
举报

gcc常见编译选项

  • ** -c **:只激活预处理、编译和汇编,也就是生成obj文件
  • ** -S **:只激活处理和编译,把文件编译成汇编代码
  • ** -o **:定制目标名称,缺省的时候编译出来的可执行程序名为a.exe(windows)或a.out(linux)
  • ** -Wall **:打开一些很有用的编译警告
  • ** -std **:指定C标准,如-std=99,使用C99标准
  • ** -g **:指示编译器,编译的时候添加调试信息
  • ** -O0 -O1 -O2 -O3 **:编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高
/*
file_name: swap.c
*/

#include<stdio.h>
void swap(int a, int b)
{
	int t;
	t = a;
	a = b;
	b = t;
}

int main()
{
    int a=3, b=4;
	swap(a,b);
	printf("%d %d",a,b);
	return 0;
}

GDB的使用

什么是GDBhttps://www.bing.com/knows/search?q=gdb&mkt=zh-cn&FORM=BKACAI http://www.gnu.org/software/gdb/

一般来说,GDB主要帮助你完成以下四个方面的内容 1、启动你的程序,可以按照你的自定义的要求随心所欲的运行程序 2、可以让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式) 3、当程序被停住时,可以检查此时你的程序中所发生的事 4、你可以改变你的程序,将一个BUG产生的影响修正,从而测试其他BUG

GDB常见命令

简称

全称

备注

l

list

显示指定行号或者指定函数附近的源代码

b

break

在指定行号或指定函数开头设置断点

r

run

运行程序,直到程序结束或遇到断点

c

continue

在程序中断后继续执行程序,直到程序结束或遇到断点停下。注意在程序开始执行前只能用r,而不能用c

n

next

执行一条语句。如果有函数调用,则把它当做一个整体

s

step

执行一条语句。如果有函数调用,则进入函数内部

u

until

执行到指定行号或指定函数的开头

p

print

显示变量或表达式的值

disp

display

把一个表达式设置为display,当程序每次停下来时都会显示其值

cl

clear

取消断点,和b格式相同,如果该位置有多个断点,将同时取消

i

info

显示各种信息,如i b显示所有断点,i disp显示display,而i lo显示所有局部变量

bt

backtrace

打印所有栈帧信息

调用栈(Call Stack)

调用栈描述的是函数之间的调用关系。调用栈由栈帧(Stack Frame)组成,每个栈帧对应着一个未运行完的函数。在GDB中可以用backtrace(简称bt)命令打印所有栈帧信息。若要用p命令打印一个非当前栈帧的局部变量,可以用frame命令选择另一个栈帧

拿个程序来玩玩,swap.c文件

#include<stdio.h>
void swap(int a, int b){
	int t;t = a;a = b;b = t;
}

int main(){
    int a=3, b=4;
	swap(a,b);
	printf("%d %d",a,b);
	return 0;
}

* 程序的目的是交换a和b的值,然而并没有交换交换成功 *

原因:

  • 函数的形参和在函数内部声明的变量都是该函数的局部变量。无法访问其他函数的局部变量。
  • 局部变量的存储空间是临时分配的,函数执行完毕时,局部变量的空间将被释放,其中的值无法保留到下次使用。
  • 如果要实现真正的交换,我们应该传入的是存储变量的地址,此时函数swap的形参类型应该为指针类型

PS: C语言的变量都是放在内存中的,而内存中间的每一个字节都有一个称为地址(address)的编号。 每一个变量都占有一定数目的字节(可以用sizeof运算符获得),其中第一个字节的地址称为变量的地址。

o(*≧▽≦)ツ┏━┓拿个递归程序来玩玩

#include<stdio.h>
int f(int n)
{
	return n == 0 ? 1 : f(n-1)*n;
}
int main()
{
	printf("%d\n",f(3));
	return 0;
}

在C语言的函数中,调用自己和调用其他函数没有任何本质区别,都是建立新栈帧,传递参数并修改当前代码行。在函数执行体完毕后删除栈帧,处理返回值,并修改当前代码行数。

以上调用栈的一个比喻 皇帝(拥有main函数的栈帧):大臣,你给我算下f(3) 大臣(拥有f(3)的栈帧):知府,你给我算下f(2) 知府(拥有f(2)的栈帧):县令,你给我算下f(1) 县令(拥有f(1)的栈帧):师爷,你给我算下f(0) 师爷(拥有f(0)的栈帧):回老爷,f(0)=1 县令(心算f(1)=f(0)1=1):回知府大人,f(1)=1 知府(心算f(2)=f(1)2=2):回大人,f(2)=2 大臣(心算f(3)=f(2)*3=6):回皇上,f(3)=6 皇上满意了

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年12月3日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • gcc常见编译选项
  • GDB的使用
    • GDB常见命令
      • 调用栈(Call Stack)
        • 拿个程序来玩玩,swap.c文件
        • o(*≧▽≦)ツ┏━┓拿个递归程序来玩玩
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档