当前位置:文档之家› gdb查看堆栈

gdb查看堆栈

gdb查看堆栈
gdb查看堆栈

8Examining the Stack查看堆栈

When your program has stopped,the first thing you need to know is where it stopped and

how it got there.

当你的程序到暂停到断点处时,你需要知道的第一件事就是知道程序停在哪儿,以及

通过什么样的函数调用关系到达这里的。

Each time your program performs a function call,information about the call is generated.

That information includes the location of the call in your program,the arguments of the

call,and the local variables of the function being called.The information is saved in a block

of data called a stack frame.The stack frames are allocated in a region of memory called

the call stack.

每当你的程序调用一个函数,这个函数的相关信息将会生成,这信息包括这个函数在

程序中的位置,函数的参数,以及被调函数局部变量的值。这些信息保存在一个数据

块中,这个数据块叫做栈框。这些栈框位于内存中称为栈的区域。

When your program stops,the gdb commands for examining the stack allow you to see

all of this information.

当你的程序断点处停止,gdb查看堆栈的命令允许你看所有函数相关的信息。

One of the stack frames is selected by gdb and many gdb commands refer implicitly

to the selected frame.In particular,whenever you ask gdb for the value of a variable in

your program,the value is found in the selected frame.There are special gdb commands to

select whichever frame you are interested in.See Section8.3[Selecting a Frame],page88.

When your program stops,gdb automatically selects the currently executing frame and describes it briefly,similar to the frame command(see Section8.4[Information about a Frame],page89).

gdb将会选择其中的某个栈框。如果没有明确指出栈框,很多gdb命令也隐含地指出了选择的栈框。特别是,当你使用gdb查看你程序中某个变量的值时。这个值将会在指定的某个栈框中找到。这儿有几个gdb命令去选择你感兴趣的栈框。看Section8.3,88页,当程序停止后,gdb将会自动选择当前执行的栈框。以及简单地描述它。和后面要说的栈框的命令相似

8.1Stack Frames(栈框)

The call stack is divided up into contiguous pieces called stack frames,or frames for short;

each frame is the data associated with one call to one function.The frame contains the arguments given to the function,the function’s local variables,and the address at which

the function is executing.

栈被划分成多个连续的块,每个块称为栈框,或短框;每个栈框都存有与调用函数相关的数据。栈框中包含了调用函数的参数,调用函数的局部变量。以及这个函数的执行的地址。

When your program is started,the stack has only one frame,that of the function main.

This is called the initial frame or the outermost frame.Each time a function is called,a

new frame is made.Each time a function returns,the frame for that function invocation

is eliminated.If a function is recursive,there can be many frames for the same function.

The frame for the function in which execution is actually occurring is called the innermost

frame.This is the most recently created of all the stack frames that still exist.

Inside your program,stack frames are identified by their addresses.A stack frame

consists of many bytes,each of which has its own address;each kind of computer has a convention for choosing one byte whose address serves as the address of the https://www.doczj.com/doc/e11987117.html,ually

this address is kept in a register called the frame pointer register(see Section10.12[Registers], page126)while execution is going on in that frame.

当程序开始执行时,栈上就只有一个栈框,也就是用来描述Main函数的。这个栈框称为初始化栈框或最外层栈框。每当调用一个函数,一个新的栈框将会生成。每当一个函数结束,该函数对应的栈框将会消除。如果一个函数是递归函数,这将会对同一个函数产生很多个栈框。正在执行函数的栈框将叫做最内层栈框。这个是所有存在栈框中最新创建的。

在你的程序里,栈框通过它对应到的地址进行标识。一个栈框由多个字节组成,每个栈框都有自己的地址,当程序执行到这个栈框时。通常这个栈框地址存放在特定的寄存器中(看Section10.12[Registers],126页),

gdb assigns numbers to all existing stack frames,starting with zero for the innermost

frame,one for the frame that called it,and so on upward.These numbers do not really

exist in your program;they are assigned by gdb to give you a way of designating stack

frames in gdb commands.

gdb为每个存在的栈框赋上一个标号。标号从0开始,0表示最里层的栈框。也就是正在被调用函数的栈框。这些标号在程序中并不存在,它是由gdb赋予的,gdb通过赋予这个标号来给gdb的命令指定哪个栈框。

Some compilers provide a way to compile functions so that they operate without stack

frames.(For example,the gcc option‘-fomit-frame-pointer’generates functions without a frame.) This is occasionally done with heavily used library functions to save the frame setup time.gdb has limited facilities for dealing with

Debugging with gdb

these function invocations.If the innermost function invocation has no stack

frame,gdb

nevertheless regards it as though it had a separate frame,which is numbered

zero as usual,

allowing correct tracing of the function call chain.However,gdb has no

provision for

frameless functions elsewhere in the stack.

frame args

The frame command allows you to move from one stack frame to another,and

to print the stack frame you select.args may be either the address of the frame

or the stack frame number.Without an argument,frame prints the current

stack frame.

这个frame命令允许你从一个栈框移动到另一个栈框,然后可以打印出你选择的栈框,args 要么是栈框的地址,要么是栈框的标号,如果没有参数,frame命令将会打印出当前的栈框。select-frame

The select-frame command allows you to move from one stack frame to another without printing

the frame.This is the silent version of frame.

select-frame命令允许你从一个栈框移动到另外一个栈框而不打印栈框的信息,

这个命令可以看作是frame命令的silent版本。

8.2Backtraces

A backtrace is a summary of how your program got where it is.It shows one line per frame,

for many frames,starting with the currently executing frame(frame zero),followed by its

caller(frame one),and on up the stack.

Backtrace命令是查看你程序通过什么样的函数调用关系到达这断点的概括。它将为每个栈框显示一行。对于多个栈框,从当前执行的那个栈框开始,接下来就是显示调用正在执行函数的函数的栈框。

backtrace

bt

Print a backtrace of the entire stack:one line per frame for all frames in the

stack.

Bt命令打印栈全部的backtrace,每个栈框显示一行。

You can stop the backtrace at any time by typing the system interrupt charac-ter,normally Ctrl-c.你可以在任何时间结束backtrace通过键入系统中断字符,ctrl+c

backtrace n

bt n

Similar,but print only the innermost n frames.

bt n命令将会显示最内层的n个栈框。

backtrace-n

bt-n

Similar,but print only the outermost n frames.

bt-n将会显示最外层的n个栈框。

backtrace full

bt full

bt full n

bt full-n

Print the values of the local variables also.n specifies the number of frames to

print,as described above.

如果添加full这个参数的话,将会显示栈框中的局部变量。

The names where and info stack(abbreviated info s)are additional aliases for backtrace.

In a multi-threaded program,gdb by default shows the backtrace only for the current

thread.To display the backtrace for several or all of the threads,use the command thread

apply(see Section4.10[Threads],page35).For example,if you type thread apply all backtrace,gdb will display the backtrace for all the threads;this is handy when you debug

a core dump of a multi-threaded program.Each line in the backtrace shows the frame number

and the function name.The program counter value is also shown—unless you use set print address off.The backtrace also shows the source file name and line number,as well as

the arguments to the function.The

program counter value is omitted if it is at the beginning of the code for that line number.

Here is an example of a backtrace.It was made with the command‘bt3’,so it

shows

the innermost three frames.

这儿是一个backtrace的例子。如下的显示是通过执行bt3生成的,所以显示的是最内层的3个栈框。

#0

m4_traceon(obs=0x24eb0,argc=1,argv=0x2b8c8)

at builtin.c:993

#10x6e38in expand_macro(sym=0x2b600,data=...)at macro.c:242

#20x6840in expand_token(obs=0x0,t=177664,td=0xf7fffb08)

at macro.c:71

(More stack frames follow...)

The display for frame zero does not begin with a program counter value,indicating that

your program has stopped at the beginning of the code for line993of builtin.c.

The value of parameter data in frame1has been replaced by....By default,gdb prints

the value of a parameter only if it is a scalar(integer,pointer,enumeration,etc).See

command set print frame-arguments in Section10.8[Print Settings],page113for more

details on how to configure the way function parameter values are printed.

If your program was compiled with optimizations,some compilers will optimize away arguments passed to functions if those arguments are never used after the call.Such optimizations generate code that passes arguments through registers,but doesn’t store those arguments in the stack frame.gdb has no way of displaying such arguments in stack frames

other than the innermost one.Here’s what such a backtrace might look like:

#0

m4_traceon(obs=0x24eb0,argc=1,argv=0x2b8c8)

at builtin.c:993

#10x6e38in expand_macro(sym=)at macro.c:242

#20x6840in expand_token(obs=0x0,t=,td=0xf7fffb08)

at macro.c:71

(More stack frames follow...)

The values of arguments that were not saved in their stack frames are shown

as‘

out>’.

If you need to display the values of such optimized-out arguments,either

deduce that

from other variables whose values depend on the one you are interested in,or

recompile

without optimizations.

Most programs have a standard user entry point—a place where system

libraries and

startup code transition into user code.For C this is main1.When gdb finds

the entry

function in a backtrace it will terminate the backtrace,to avoid tracing into

highly system-

specific(and generally uninteresting)code.

If you need to examine the startup code,or limit the number of levels in a

backtrace,

you can change this behavior:

set backtrace past-main

set backtrace past-main on

Backtraces will continue past the user entry point.

set backtrace past-main off

Backtraces will stop when they encounter the user entry point.This is the

default.

show backtrace past-main

Display the current user entry point backtrace policy.

1

Note that embedded programs(the so-called“free-standing”environment)are

not required to have a

main function as the entry point.They could even have multiple entry points.

88

Debugging with gdb

set backtrace past-entry

set backtrace past-entry on

Backtraces will continue past the internal entry point of an application.This

entry point is encoded by the linker when the application is built,and is likely

before the user entry point main(or equivalent)is called.

set backtrace past-entry off

Backtraces will stop when they encounter the internal entry point of an appli-

cation.This is the default.

show backtrace past-entry

Display the current internal entry point backtrace policy.

set backtrace limit n

set backtrace limit0

Limit the backtrace to n levels.A value of zero means unlimited.

show backtrace limit

Display the current limit on backtrace levels.

8.3Selecting a Frame选择某个栈框

Most commands for examining the stack and other data in your program work on whichever stack frame is selected at the moment.Here are the commands for selecting a stack frame;

all of them finish by printing a brief description of the stack frame just selected.

很多gdb为查看堆栈和里面的数据提供了很多子命令,这儿就有选择栈框的一些命令。frame n

fn

Select frame number n.Recall that frame zero is the innermost(currently

executing)frame,frame one is the frame that called the innermost one,and so

on.The highest-numbered frame is the one for main.

frame n(fn)将会选择栈框n,栈框0是最内层的栈框,也就是当前执行的函数,栈框1

是调用最内层栈框的函数。最大的栈框就是main函数对应的栈框。

frame addr

f addr

Select the frame at address addr.This is useful mainly if the chaining of stack

frames has been damaged by a bug,making it impossible for gdb to assign

numbers properly to all frames.In addition,this can be useful when your

program has multiple stacks and switches between them.

通过栈框的地址选择栈框。如果栈框被bug破坏掉了,这将是主要的方法去查看栈框。栈框破坏掉了,gdb将不能通过栈框标号去定位栈框。另外,如果你的程序有多个栈,在多个栈切换时这中方法将很有用。

On the SPARC architecture,frame needs two addresses to select an arbitrary

frame:a frame pointer and a stack pointer.

On the MIPS and Alpha architecture,it needs two addresses:a stack pointer

and a program counter.

On the29k architecture,it needs three addresses:a register stack pointer,a

program counter,and a memory stack pointer.

up n Move n frames up the stack.For positive numbers n,this advances

toward the outermost frame,to higher frame numbers,to frames that have existed

Longer.n defaults to one.

up n将会朝外层栈框走n个。它的方向是朝最外层的栈框,也就是最大的栈框号

down n Move n frames down the stack.For positive numbers n,this advances

toward the innermost frame,to lower frame numbers,to frames that were created

more recently.n defaults to one.You may abbreviate down as do.

down n和up n是对应的,它将会朝最内层走n个栈框。

All of these commands end by printing two lines of output describing the

frame.The first line shows the frame number,the function name,the arguments,and the

source file and line number of execution in that frame.The second line shows the text of

that source line.

这些命令将会打印两行关于该栈框的信息,第一行将会显示栈框号,函数名,参数,以及源代码所在的文件名,和所在的行。

For example:

(gdb)up

#10x22f0in main(argc=1,argv=0xf7fffbf4,env=0xf7fffbfc)

at env.c:10

10

read_input_file(argv[i]);

After such a printout,the list command with no arguments prints ten lines

centered on

the point of execution in the frame.You can also edit the program at the point

of execution

with your favorite editing program by typing edit.See Section9.1[Printing Source Lines],

page91,for details.

up-silently n

down-silently n

These two commands are variants of up and down,respectively;they differ in that they do their work silently,without causing display of the new frame. They

are intended primarily for use in gdb command scripts,where the output might

be unnecessary and distracting.

8.4Information About a Frame

There are several other commands to print information about the selected stack frame.

frame

f

When used without any argument,this command does not change which frame

is selected,but prints a brief description of the currently selected stack frame. It can be abbreviated f.With an argument,this command is used to select a stack frame.See Section8.3[Selecting a Frame],page88.

info frame

info f

This command prints a verbose description of the selected stack frame,includ-ing:

?the address of the frame

?the address of the next frame down(called by this frame)

?the address of the next frame up(caller of this frame)

?the language in which the source code corresponding to this frame is written ?the address of the frame’s arguments

?the address of the frame’s local variables

?the program counter saved in it(the address of execution in the caller frame)

?which registers were saved in the frame

The verbose description is useful when something has gone wrong that has made

the stack format fail to fit the usual conventions.

Debugging with gdb

info frame addr

info f addr

Print a verbose description of the frame at address addr,without selecting

that

frame.The selected frame remains unchanged by this command.This requires

the same kind of address(more than one for some architectures)that you specify

in the frame command.See Section8.3[Selecting a Frame],page88.

info args Print the arguments of the selected frame,each on a separate line. info locals

Print the local variables of the selected frame,each on a separate line.These are all variables(declared either static or automatic)accessible at the point of execution of the selected frame.

实例—使用gdb调试器

2.4 实例—使用gdb调试器 1.编写实例程序gcctest.c,见2.2小节的开头部分 2.编译 3.启动GDB,执行程序 启动gdb,进入gdb调试环境,可以使用gdb的命令对程序进行调试。 [root@localhost gdbtest txt]# gdb //启动gdb GNU gdb Fedora (6.8-27.el5) Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i386-redhat-linux-gnu". (gdb) run gcctest //在gdb中,运行程序使用r或是run命令,注意,gcctest没有调试信息Starting program: gcctest No executable file specified. Use the "file" or "exec-file" command. //要使用file或exec-file命令指出要运行的程序 (gdb) file gcctest //使用file命令指出要运行的程序gcctest,注意,对gdb命令也可以使用Tab gcctest gcctest.c gcctestg (gdb) file gcctest //使用file命令指出要运行的程序gcctest Reading symbols from /root/Desktop/gdbtest txt/gcctest...(no debugging symbols found)...done. (gdb) r //在gdb中,运行程序使用r或是run命令 Starting program: /root/Desktop/gdbtest txt/gcctest gcctest (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) hello in main hello 1 hello 2 sum=54125560035401396161080590579269632.000000 Program exited with code 057. (gdb) file gcctestg //使用file命令指出要运行的程序gcctestg Reading symbols from /root/Desktop/gdbtest txt/gcctestg...done. (gdb) r //在gdb中,运行程序使用r或是run命令 Starting program: /root/Desktop/gdbtest txt/gcctestg gcctest hello in main hello 1 hello 2 sum=54125560035401396161080590579269632.000000 Program exited with code 057. (gdb) q //使用q或是quit命令退出gdb [root@localhost gdbtest txt]# 4.GDB命令简介

国嵌视频教程下载

嵌入式Linux视频教程 相关搜索:简体中文, 学习方法, 视频教程, 普通话, 嵌入式 中文名: 嵌入式Linux视频教程 资源格式: 光盘镜像 学校: 成都国嵌嵌入式培训中心版本: 成都国嵌嵌入式培训中心的基于广州友善之发行日期: 2010年 地区: 大陆 对白语言: 普通话 文字语言: 简体中文 视频光盘目录结构 国嵌视频1.iso -学习方法与课程体系介绍(学前必看) -学习方法介绍.avi -国嵌嵌入式课程体系.pdf -嵌入式Linux学习方法.pdf -国嵌课程1-嵌入式入门体验班(上) -第1天(嵌入式系统概述) -国嵌体验入门班-1-1(嵌入式系统概述).avi -国嵌体验入门班-1-2(ARM概述).avi -国嵌体验入门班-1-3(嵌入式Linux概述).avi -国嵌体验入门班-1-4(2440开发板介绍).avi -国嵌体验入门班-1-5(软硬件环境搭建).avi -第2天(开发板快乐体验) -国嵌体验入门班-2-1(开发板系统安装).avi -国嵌体验入门班-2-1(开发板系统安装-Jlink方式).avi -国嵌体验入门班-2-1(开发板系统安装-并口方式).avi -国嵌体验入门班-2-2(裸机程序体验).avi -国嵌体验入门班-2-3(QT系统体验).avi -国嵌体验入门班-2-4(Android系统体验).avi 国嵌视频2.iso

-国嵌课程1-嵌入式入门体验班(下) -第3天(Linux系统体验) -国嵌体验入门班-3-1(Linux定制安装).avi -国嵌体验入门班-3-2(Linux命令).avi -国嵌体验入门班-3-3(VI使用).avi -国嵌体验入门班-3-4(Linux系统管理).avi -国嵌体验入门班-3-5(Shell编程).avi -国嵌体验入门班-3-6(Qcd功能演示).avi -国嵌体验入门班-3-7(必修实验).avi -国嵌课程2-嵌入式Linux应用开发班 -第1天(编程基础) -国嵌应用班-1-1(GCC程序编译).avi -国嵌应用班-1-2(GDB程序调试).avi -国嵌应用班-1-3(makefile工程管理).avi -国嵌应用班-1-4(必修实验).avi -第2天(文件时间编程) -国嵌应用班-2-1(系统调用方式访问文件).avi -国嵌应用班-2-2(库函数访问文件).avi -国嵌应用班-2-3(时间编程).avi -国嵌应用班-2-4(必修实验).avi -第3天(多进程程序设计) -国嵌应用班-3-1(进程控制原理).avi -国嵌应用班-3-2(进程控制程序设计).avi -国嵌应用班-3-3(必修实验).avi -第4天(进程间通讯) -国嵌应用班-4-1(进程间通讯概述).avi -国嵌应用班-4-2(管道通讯).avi -国嵌应用班-4-3(信号通讯).avi -国嵌应用班-4-4(共享内存通讯).avi -国嵌应用班-4-5(必修实验).avi -第5天(进程间通讯) -国嵌应用班-5-1(消息队列).avi

gdb单步调试(中)

一、设置断点(BreakPoint ) 我们用break 命令来设置断点。正面有几点设置断点的方法: break 在进入指定函数时停住。C++ 中可以使用class::function 或function(type,type) 格式来指定函数名。 break 在指定行号停住。 break +offset break -offset 在当前行号的前面或后面的offset 行停住。offiset 为自然数。 break filename:linenum 在源文件filename 的linenum 行处停住。 break filename:function 在源文件filename 的function 函数的入口处停住。 break *address 在程序运行的内存地址处停住。 break break 命令没有参数时,表示在下一条指令处停住。 break ... if ... 可以是上述的参数,condition 表示条件,在条件成立时停住。比如在循环境体中,可以设置break if i=100 ,表示当i 为100 时停住程序。 查看断点时,可使用info 命令,如下所示:(注:n 表示断点号) info breakpoints [n] info break [n] 二、设置观察点(WatchPoint ) 观察点一般来观察某个表达式(变量也是一种表达式)的值是否有变化了,如果有变化,马上停住程序。我们有下面的几种方法来设置观察点: watch 为表达式(变量)expr 设置一个观察点。一量表达式值有变化时,马上停住程序。 rwatch

gbd调试

用GDB调试程序 GDB概述 ———— GDB 是GNU开源组织发布的一个强大的UNIX下的程序调试工具。或许,各位比较喜欢那种图形界面方式的,像VC、BCB等IDE的调试,但如果你是在 UN IX平台下做软件,你会发现GDB这个调试工具有比VC、BCB的图形化调试器更强大的功能。所谓“寸有所长,尺有所短”就是这个道理。 一般来说,GDB主要帮忙你完成下面四个方面的功能: 1、启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。 2、可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式) 3、当程序被停住时,可以检查此时你的程序中所发生的事。 4、动态的改变你程序的执行环境。 从上面看来,GDB和一般的调试工具没有什么两样,基本上也是完成这些功能,不过在细节上,你会发现GDB这个调试工具的强大,大家可能比较习惯了图形化的调试工具,但有时候,命令行的调试工具却有着图形化工具所不能完成的功能。让我们一一看来。 一个调试示例 —————— 源程序:tst.c

1 #include 2 3 int func(int n) 4 { 5 int sum=0,i; 6 for(i=0; i cc -g tst.c -o tst 使用GDB调试:

GDB调试精粹及使用实例

GDB调试精粹及使用实例 一:列文件清单 1. List (gdb) list line1,line2 二:执行程序 要想运行准备调试的程序,可使用run命令,在它后面可以跟随发给该程序的任何参数,包括标准输入和标准输出说明符(<和>)和外壳通配符(*、?、[、])在内。 如果你使用不带参数的run命令,gdb就再次使用你给予前一条run命令的参数,这是很有用的。 利用set args 命令就可以修改发送给程序的参数,而使用show args 命令就可以查看其缺省参数的列表。 (gdb)set args –b –x (gdb) show args backtrace命令为堆栈提供向后跟踪功能。 Backtrace 命令产生一张列表,包含着从最近的过程开始的所以有效过程和调用这些过程的参数。 三:显示数据 利用print 命令可以检查各个变量的值。 (gdb) print p (p为变量名) whatis 命令可以显示某个变量的类型 (gdb) whatis p type = int * print 是gdb的一个功能很强的命令,利用它可以显示被调试的语言中任何有效的表达式。表达式除了包含你程序中的变量外,还可以包含以下内容: l 对程序中函数的调用 (gdb) print find_entry(1,0) l 数据结构和其他复杂对象 (gdb) print *table_start $8={e=reference=’\000’,location=0x0,next=0x0} l 值的历史成分 (gdb)print $1 ($1为历史记录变量,在以后可以直接引用 $1 的值) l 人为数组 人为数组提供了一种去显示存储器块(数组节或动态分配的存储区)内容的方法。早期的调试程序没有很好的方法将任意的指针换成一个数组。就像对待参数一样,让我们查看内存中在变量h后面的10个整数,一个动态数组的语法如下所示: base@length 因此,要想显示在h后面的10个元素,可以使用h@10: (gdb)print h@10 $13=(-1,345,23,-234,0,0,0,98,345,10)

GDB调试及实例

GDB调试及实例 一:列文件清单 1.List (gdb) list line1,line2 二:执行程序 要想运行准备调试的程序,可使用run命令,在它后面可以跟随发给该程序的任何参数,包括标准输入和标准输出说明符(<和>)和外壳通配符(*、?、[、])在内。 如果你使用不带参数的run命令,gdb就再次使用你给予前一条run命令的参数,这是很有用的。 利用set args 命令就可以修改发送给程序的参数,而使用show args 命令就可以查看其缺省参数的列表。 (gdb)set args –b –x (gdb) show args backtrace命令为堆栈提供向后跟踪功能。 Backtrace 命令产生一张列表,包含着从最近的过程开始的所以有效过程和调用这些过程的参数。 三:显示数据 利用print 命令可以检查各个变量的值。 (gdb) print p (p为变量名) whatis 命令可以显示某个变量的类型 (gdb) whatis p type = int * print 是gdb的一个功能很强的命令,利用它可以显示被调试的语言中任何有效的表达式。表达式除了包含你程序中的变量外,还可以包含以下内容: l 对程序中函数的调用 (gdb) print find_entry(1,0) l 数据结构和其他复杂对象 (gdb) print *table_start $8={e=reference=’\000’,location=0x0,next=0x0} l 值的历史成分 (gdb)print $1 ($1为历史记录变量,在以后可以直接引用$1 的值) l 人为数组 人为数组提供了一种去显示存储器块(数组节或动态分配的存储区)内容的方法。早期的调试程序没有很好的方法将任意的指针换成一个数组。就像对待参数一样,让我们查看内存中在变量h后面的10个整数,一个动态数组的语法如下所示: base@length 因此,要想显示在h后面的10个元素,可以使用h@10: (gdb)print h@10 $13=(-1,345,23,-234,0,0,0,98,345,10)

如何在Linux中使用gdb调试C程序

如何在Linux中使用gdb调试C程序 无论多么有经验的程序员,开发的任何软件都不可能完全没有bug。因此,排查及修复bug 成为软件开发周期中最重要的任务之一。有许多办法可以排查bug(测试、代码自审等等),但是还有一些专用软件(称为调试器)可以帮助准确定位问题的所在,以便进行修复。 如果你是C/C++ 程序员,或者使用Fortran 和Modula-2 编程语言开发软件,那么你将会很乐意知道有这么一款优秀的调试器- GDB - 可以帮你更轻松地调试代码bug 以及其它问题。在这篇文章中,我们将讨论一下GDB 调试器的基础知识,包括它提供的一些有用的功能/选项。 在我们开始之前,值得一提的是,文章中的所有说明和示例都已经在Ubuntu 14.04 LTS 中测试过。教程中的示例代码都是 C 语言写的;使用的shell 为bash(4.3.11);GDB 版本为7.7.1。 GDB 调试器基础 通俗的讲,GDB 可以让你看到程序在执行过程时的内部流程,并帮你明确问题的所在。我们将在下一节通过一个有效的示例来讨论GDB 调试器的用法,但在此之前,我们先来探讨一些之后对你有帮助的基本要点。 首先,为了能够顺利使用类似GDB 这样的调试器,你必须以指定的方式编译程序,让编译器产生调试器所需的调试信息。例如,在使用gcc 编译器(我们将在本教程之后的章节用它来编译C 程序示例)编译代码的时候,你需要使用 -g 命令行选项。 IT网,http://it 想要了解gcc 编译器手册页中关于 -g 命令行选项相关的内容,请看这里。 下一步,确保在你的系统中已经安装GDB 调试器。如果没有安装,而且你使用的是基于Debian 的系统(如Ubuntu),那么你就可以使用以下命令轻松安装该工具: sudo apt-get install gdb 在其他发行版上的安装方法,请看这里。 现在,当你按照上述的方式编译完程序(gcc -g 命令行选项),同时也已经安装好GDB 调

用GDB调试程序--调试器GDB常用功能

一,GDB调试器简介 GDB是Linux下的常用调试器,主要用于调试源代码、调试运行中的进程和查看core dump文件。Linux下的调试器主要有gdb、cgdb、ddd、eclipse。GDB调试器的运行速度快、能够进行源代码同步显示。 使用-tui 选项开启gdb命令输入和源代码的分屏显示,tui即Terminal User Interface。 二,GDB常用调试命令 a)调试可执行文件 以源代码为/home/zebra/目录下的test.c文件产生的可执行文件test为例(可执行文件使用gcc进行编译,并使用-g选项以产生调试信息),进行命令的说明(详细源代码参见第三部分:三,调试实例分析 )。 gdb调试源代码流程: 1,开启gdb程序,即运行如下命令:gdb -q (-q用以使得gdb不输出gdb程序的版本等信息)2,指定调试的二进制文件:file test 3,list查看源代码 4,设定断点breakpoint main breakpoint sub 上述分别在main函数和sub函数处设定了断点。 断点可以设置在任意已知源代码文件的某一行,某一个函数,同时可以指定是设置在哪个/哪些线程上(见下边描述)。 5,运行可执行文件: run 6,这样程序会运行到断点处停止下来,gdb会打印当前断点的信息。 7,使用s 或者n进行单步调试。 s即step,n即next都是执行一条语句,然后停下来。 如果想执行一条汇编语句,则可以使用si ,ni,即step instruction,next instruction。 8,bt命令查看当前的调用栈,bt即backtrace。 9,info frame查看函数帧信息。 10,frame n 进入某个函数帧(编号为n) 11,info 命令可以对当前的函数帧的寄存器、局部变量、函数的参数进行查看。 info register;info local;info args。 12,disassemble对当前函数对应的二进制进行反汇编。 13,x/nfu address 查看内存其中address是内存开始的地址,从该地址向高地址增加, x是examinate的缩写,n表示重复次数,f表示输出格式,u表示内存大小的单位(默认是字,即4个字节)。 一般我都用x/nx address,即打印n个从address开始的内存,每个是4字节,以十六进制打印。14,continue,执行至该函数退出 15,info threads,显示当前可调试的所有线程 16,thread ,切换当前调试的线程为指定ID的线程break File:LineNumber thread if x==y。 17,thread apply command让一个/多个/所有线程执行GDB的命令command。

linux下的静态库与动态库的区别,Gdb调试段错误,自动生成Makefile

linux下的静态库与动态库的区别 1.什么是库 在windows平台和linux平台下都大量存在着库。 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。 由于windows和linux的本质不同,因此二者库的二进制是不兼容的。 2.库的种类 linux下的库有两种:静态库和共享库(动态库)。 二者的不同点在于代码被载入的时刻不同。 静态库的代码在编译过程中已经被载入可执行程序,因此体积较大。 共享库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小。 3.库存在的意义 库是别人写好的现有的,成熟的,可以复用的代码,你可以使用但要记得遵守许可协议。现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。 共享库的好处是,不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例。 4.库文件是如何产生的在linux下 静态库的后缀是.a,它的产生分两步 Step 1.由源文件编译生成一堆.o,每个.o里都包含这个编译单元的符号表 Step 2.ar命令将很多.o转换成.a,成文静态库 动态库的后缀是.so,它由gcc加特定参数编译产生。 例如: $ gcc -fPIC -c *.c $ gcc -shared -Wl,-soname, libfoo.so.1 -o libfoo.so.1.0 *. 5.库文件是如何命名的,有没有什么规范 在linux下,库文件一般放在/usr/lib /lib下, 静态库的名字一般为libxxxx.a,其中xxxx是该lib的名称 动态库的名字一般为libxxxx.so.major.minor,xxxx是该lib的名称,major是主版本号,minor是副版本号 6.如何知道一个可执行程序依赖哪些库 ldd命令可以查看一个可执行程序依赖的共享库, 例如# ldd /bin/lnlibc.so.6 => /lib/libc.so.6 (0×40021000)/lib/ld-linux.so.2 => /lib/ld- linux.so.2 (0×40000000) 可以看到ln命令依赖于libc库和ld-linux库 Gdb调试段错误 1.段错误是什么

GDB基本命令

1. 本文介绍使用gdb调试程序的常用命令。 主要内容: [简介] [举例] [其他] [简介] ============= GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。如果你是在UNIX平台下做软件,你会发现GDB这个调试工具有比VC、BCB的图形化调试器更强大的功能。同时GDB也具有例如ddd这样的图形化的调试端。 一般来说,GDB主要完成下面四个方面的功能: (1)启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。 (2)可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式) (3)当程序被停住时,可以检查此时你的程序中所发生的事。 (4)动态的改变你程序的执行环境。 [举例] ============= *启动gdb $gdb 这样可以和gdb进行交互了。 *启动gdb,并且分屏显示源代码: $gdb -tui 这样,使用了'-tui'选项,启动可以直接将屏幕分成两个部分,上面显示源代码,比用list方便多了。这时候使用上下方向键可以查看源代码,想要命令行使用上下键就用[Ctrl]n和[Ctrl]p. *启动gdb调试指定程序app: $gdb app 这样就在启动gdb之后直接载入了app可执行程序,需要注意的是,载入的app程序必须在编译的

时候有gdb调试选项,例如'gcc -g app app.c',注意,如果修改了程序的源代码,但是没有编译,那么在gdb中显示的会是改动后的源代码,但是运行的是改动前的程序,这样会导致跟踪错乱的。 *启动程序之后,再用gdb调试: $gdb 这里,是程序的可执行文件名,是要调试程序的PID.如果你的程序是一个服务程序,那么你可以指定这个服务程序运行时的进程ID。gdb会自动attach上去,并调试他。program应该在PATH环境变量中搜索得到。 *启动程序之后,再启动gdb调试: $gdb 这里,程序是一个服务程序,那么你可以指定这个服务程序运行时的进程ID,是要调试程序的PID.这样gdb就附加到程序上了,但是现在还没法查看源代码,用file命令指明可执行文件就可以显示源代码了。 **启动gdb之后的交互命令: 交互命令支持[Tab]补全。 *显示帮助信息: (gdb) help *载入指定的程序: (gdb) file app 这样在gdb中载入想要调试的可执行程序app。如果刚开始运行gdb而不是用gdb app启动的话可以这样载入app程序,当然编译app的时候要加入-g调试选项。 *重新运行调试的程序: (gdb) run 要想运行准备调试的程序,可使用run命令,在它后面可以跟随发给该程序的任何参数,包括标准输入和标准输出说明符(<和> )和shell通配符(*、?、[、])在内。

LINUX gdb调试命令手册

常用的gdb命令 backtrace 显示程序中的当前位置和表示如何到达当前位置的栈跟踪(同义词:where)breakpoint 在程序中设置一个断点 cd 改变当前工作目录 clear 删除刚才停止处的断点 commands 命中断点时,列出将要执行的命令 continue 从断点开始继续执行 delete 删除一个断点或监测点;也可与其他命令一起使用 display 程序停止时显示变量和表达时 down 下移栈帧,使得另一个函数成为当前函数 frame 选择下一条continue命令的帧 info 显示与该程序有关的各种信息 jump 在源程序中的另一点开始运行 kill 异常终止在gdb 控制下运行的程序 list 列出相应于正在执行的程序的原文件内容 next 执行下一个源程序行,从而执行其整体中的一个函数 print 显示变量或表达式的值 pwd 显示当前工作目录 pype 显示一个数据结构(如一个结构或C++类)的内容 quit 退出gdb reverse-search 在源文件中反向搜索正规表达式 run 执行该程序 search 在源文件中搜索正规表达式 set variable 给变量赋值 signal 将一个信号发送到正在运行的进程 step 执行下一个源程序行,必要时进入下一个函数 undisplay display命令的反命令,不要显示表达式 until 结束当前循环 up 上移栈帧,使另一函数成为当前函数 watch 在程序中设置一个监测点(即数据断点) whatis 显示变量或函数类型

GDB命令分类详解 一:列文件清单 (2) 二:执行程序 (2) 三:显示数据 (2) 四:断点(breakpoint) (3) 五.断点的管理 (3) 六.变量的检查和赋值 (4) 七.单步执行 (4) 八.函数的调用 (4) 九.机器语言工具 (4) 十.信号 (4) 十一.原文件的搜索 (5) 十二. UNIX接口 (5) 十三. 命令的历史 (5) 十四. GDB帮助 (5) 十五. GDB多线程 (6) 十六. GDB使用范例 (7) 一:列文件清单 1.List (gdb) list line1,line2 二:执行程序 要想运行准备调试的程序,可使用run命令,在它后面可以跟随发给该程序的任何参数,包括标准输入和标准输出说明符(<和>)和外壳通配符(*、?、[、])在内。 如果你使用不带参数的run命令,gdb就再次使用你给予前一条run命令的参数,这是很有用的。 利用set args 命令就可以修改发送给程序的参数,而使用show args 命令就可以查看其缺省参数的列表。 (gdb)set args –b –x (gdb) show args backtrace命令为堆栈提供向后跟踪功能。 Backtrace 命令产生一张列表,包含着从最近的过程开始的所以有效过程和调用这些过程的参数。 三:显示数据 利用print 命令可以检查各个变量的值。 (gdb) print p (p为变量名) whatis命令可以显示某个变量的类型 (gdb) whatis p type = int * print 是gdb的一个功能很强的命令,利用它可以显示被调试的语言中任何有效的表达式。表达式除了包含你程序中的变量外,还可以包含以下内容:

用 GDB 调试程序

用 GDB 调试程序 用 gdb 调试 GCC 程序 Linux 包含了一个叫 gdb 的 GNU 调试程序. gdb 是一个用来调试 C 和 C++ 程序的强力调试器. 它使你能在程序运行时观察程序的内部结构和内存的使用情况. 以下是 gdb 所提供的一些功能: ?它使你能监视你程序中变量的值. ?它使你能设置断点以使程序在指定的代码行上停止执行. ?它使你能一行行的执行你的代码. 在命令行上键入 gdb 并按回车键就可以运行 gdb 了, 如果一切正常的话, gdb 将被启动并且你将在屏幕上看到类似的内容: GDB is free software and you are welcome to 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. GDB 4.14 (i486-slakware-linux), Copyright 1995 Free Software Foundation, Inc. (gdb) 当你启动 gdb 后, 你能在命令行上指定很多的选项. 你也可以以下面的方式来运行 gdb : gdb 当你用这种方式运行 gdb , 你能直接指定想要调试的程序. 这将告诉gdb 装入名为 fname 的可执行文件. 你也可以用 gdb 去检查一个因程序异常终止而产生的 core 文件, 或者与一个正在运行的程序相连. 你可以参考 gdb 指南页或在命令行上键入 gdb -h 得到一个有关这些选项的说明的简单列表. 为调试编译代码(Compiling Code for Debugging) 为了使 gdb 正常工作, 你必须使你的程序在编译时包含调试信息. 调试信息包含你程序里的每个变量的类型和在可执行文件里的地址映射以及源代码的行号. gdb 利用这些信息使源代码和机器码相关联. 在编译时用 -g 选项打开调试选项.

gdb汇编跟踪调试与objdump查看汇编代码

gdb汇编跟踪调试与objdump查看汇编代码 使用objdump生成可读性好的汇编代码 g++ -g3 secret.cpp -o secret objdump -SIz secret -j .text > secret.s man objdump ================ 常用命令: 如何跳出for 循环 -- until 行号 如何在多重循环中监视某变量变化情况 -- watch + until 打印数组a的前10个元素 -- p o GDB 反汇编命令 set disassembly-flavor 设置ATT或INTEL格式 set disassemble-next-line 设置下一步是否显示汇编码 disas function_name 反汇编函数function_name info line function_name 查看function_name 开始和结束地址 如果调试一个stripped 的程序,就只有依赖地址了: b *0x00401365 设置断点,这个地址与没有stripped的程序相同 watch *(int*)0x00401369 设置硬件断点 ni -- 下一条指令,n 命令是无法使用的。 si -- 单步指令,s 命令也是无法使用的。 disas start_addr,end_addr 反汇编[start_addr,end_addr]之间的指令 x /3i $pc 查看eip 开始的三条指令 o 没有调试符号的实例 假设 gcc t.c (gdb) b *0x401365 Breakpoint 1 at 0x401365 (gdb) r Starting program: F:\work/a.exe [New Thread 1752.0x560] Breakpoint 1, 0x00401365 in ?? () (gdb) disas /r 0x401365,0x401370 Dump of assembler code from 0x401365to 0x401370: => 0x00401365: c7 44 24 1c 44 13 40 00 movl $0x401344,0x1c(%esp) 0x0040136d: 8b 44 241c mov 0x1c(%esp),%eax End of assembler dump. (gdb) p /x *(int*)0x401365 $1 = 0x1c2444c7

GDB调试之跨平台驱动调试

GDB调试之跨平台代码调试 一个问题引发的思考: 问题描述:使用交叉编译工具(mips64-nlm-linux-gcc) 将某一段程序编译为目标开发板上所可以使用的可执行程序后,在目标开发板上报了如下的错误: 乍一看很明显的是oops(kernel panic)了 那么我们应该如何去定位这种问题并解决呢?那就当然要用到我们的GDB了!不过是需要支持mips架构的gdb而已 一、gdb跨平台环境搭建 首先我们可以使用如下命令来查看Debian中对于体系架构的一张描述表 cat /usr/share/dpkg/archtable # i486-linux-gnu i386 ia64-linux-gnu ia64 alpha-linux-gnu alpha x86_64-linux-gnu amd64 arm-linux-gnu arm arm-linux-gnueabi armel hppa-linux-gnu hppa mips-linux-gnu mips mipsel-linux-gnu mipsel powerpc-linux-gnu powerpc s390-linux-gnu s390 sparc-linux-gnu sparc i486-gnu hurd-i386 i486-kfreebsd-gnu kfreebsd-i386

x86_64-kfreebsd-gnu kfreebsd-amd64 对于我们当前来说:我们仅仅需要 x86_64-linux-gnu amd64 mips-linux-gnu mips 明确了我们的需求,就开始生成我们自己的编译器了! 1、创建一个目录并且下载gdb源码到此目录 目录自己选择(此处为opt) //注意需要切换root mkdir /opt/build-gdb apt-get source gdb 2、根据需求配置我们的configure ./configure --enable-targets=x86_64-linux-gnu,mips-linux-gnu 3、编译 make 4、将生成的gdb复制到/usr/sbin下 cp gdb/gdb /usr/sbin/gdb-all 以上操作就可以完成跨平台gdb调试的基本安装! 二、如何使用 我们回到我们的问题的最开始: 如何定位? 1、gdb-all vmlinux (这个为开发板上所使用的vmlinx) 2、设置目标架构 set architecture mips:isa64r2 3、定位错误 info line *0x我们上述oops的epc地址 info line *0xffffffff804c120c 定位结果:第293行 Line 293 of "drivers/tl_modules/xlp_module/command_kernel/command_kernel.c" starts at address 0xffffffff804c1204 and ends at 0xffffffff804c1238 . 注意:使用info line 应首先确定DEBUG_INFO 开启(附1) 也可以查看反汇编 x/i 0xffffffff804c120c (此为查看一行,多行格式为x$numberi/address) 附1:开启DEBUG_INFO 在内核根目录执行make menucofig Symbol: DEBUG_INFO_REDUCED [=y] │Type : boolean │Prompt: Reduce debugging information │Defined at lib/Kconfig.debug:779 │Depends on: DEBUG_INFO [=y] │Location: │-> Kernel hacking │(1) -> Compile the kernel with debug info (DEBUG_INFO [=y])

GDB调试

GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。如果你是在 UNIX平台下做软件,你会发现GDB这个调试工具有比VC、 BCB的图形化调试器更强大的功能。同时GDB也具有例如ddd这样的图 形化的调试端。 一般来说,GDB主要完成下面四个方面的功能: (1)启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。 (2)可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条 件表达式) (3)当程序被停住时,可以检查此时你的程序中所发生的事。 (4)动态的改变你程序的执行环境。 兴趣是最好的老师,这里先整理总结一下在调试的过程中经常遇到的问题。带着这些问题进行学习和实践可以有助于加深印象 (1)如何打印变量的值?(print var) (2)如何打印变量的地址?(print &var) (3)如何打印地址的数据值?(print *address) (4)如何查看当前运行的文件和行?(backtrace) (5)如何查看指定文件的代码?(list file:N) (6)如何立即执行完当前的函数,但是并不是执行完整个应用程序?(finish) (7)如果程序是多文件的,怎样定位到指定文件的指定行或者函数?(list file:N) (8)如果循环次数很多,如何执行完当前的循环?(until) (9)多线程如何调试?(???)

[举例] ============= *启动gdb $gdb 这样可以和gdb进行交互了。 *启动gdb,并且分屏显示源代码: $gdb -tui 这样,使用了'-tui'选项,启动可以直接将屏幕分成两个部分,上面显示源代码,比用list方便多了。这时候使用上下方向键可以查看源代码,想要命令行使用上下键就用[Ctrl]n和[Ctrl]p. *启动gdb调试指定程序app: $gdb app 这样就在启动gdb之后直接载入了app可执行程序,需要注意的是,载入的app程序必须在编译的时候有gdb调试选项,例如'gcc -g app app.c',注意,如果修改了程序的源代码,但是没有编译,那么在gdb中显示的会是改动后的源代码,但是运行的是改动前的程序,这样会导致跟踪错乱的。 *启动程序之后,再用gdb调试: $gdb 这里,是程序的可执行文件名,是要调试程序的PID.如果你的程序是一个服务程序,那么你可以指定这个服务程序运行时的进程

gdb入门

GDB常用命令查询 gcc –g –o app main.c 在编译时给目标程序加入调试信息 gdb ./app 进入GDB调试界面 disassemble main 查看main函数的汇编 p /x *0xbffff9b8 查看内存0xbffff9b8 的内容 info registers 查看寄存器 info break 查看断点列表 info files 显示被调试文件的详细信息。 info func 显示所有的函数名称。 info local 显示当函数中的局部变量信息。 info prog 显示被调试程序的执行状态。 info var 显示所有的全局和静态变量名称。 b *0x804850d 设置断点,多用来设置汇编代码的调试 delete breakpoint 1 该命令将会删除编号1的断点,如不带编号参数,将删除所有的断点 p /x $eax 查看寄存器内容$符号,还有 $pc:程序计数器 $fp : 帧指针(当前堆栈帧) $sp : 栈指针 $ps : 处理器状态 next 不进入函数的单步执行 step 进入函数的单步执行 backtrace 显示程序中的当前位置和表示如何到达当前位置的栈跟踪(同义词:where)breakpoint 在程序中设置一个断点 cd 改变当前工作目录 clear 删除刚才停止处的断点 commands 命中断点时,列出将要执行的命令 continue 从断点开始继续执行 delete 删除一个断点或监测点;也可与其他命令一起使用 display 程序停止时显示变量和表达时 down 下移栈帧,使得另一个函数成为当前函数 frame 选择下一条continue命令的帧 info 显示与该程序有关的各种信息 jump 在源程序中的另一点开始运行 kill 异常终止在gdb 控制下运行的程序 list 列出相应于正在执行的程序的原文件内容 print 显示变量或表达式的值 pwd 显示当前工作目录 ptype 显示一个数据类型的定义(如一个结构或C++类) quit 退出gdb reverse-search 在源文件中反向搜索正规表达式 run 执行该程序

实验三、用GDB调试程序的bug

实验名称实验三用GDB调试程序的bug

(3)运行生成的可执行文件,观察运行结果。 (4)使用Cdb调试程序,通过设置断点、 单步跟踪,一步步找出错误所在。 (5)纠正错误,更改源程序并得到正确的结果。 实验步骤: (1)在工作目录上新建文件greet.c,并用vim进入文件进行编辑 (2)在Vi中输入以上代码。 (3)在Vi中保存并退出: wq。 (4)用Gcc编译: gcc -g greet.c -o greet (5)运行greet: . /greet 产生此错误的原因是少了两个头文件 #include #include 输入头文件再运行这个错误就没有了 输出为: The original string is Embedded Limux The string afterward is 可见,该程序没有能够倒序输出。 (6)启动Gdb调试: gdb greet (7)查看源代码,使用命令”l”。 (8)在30行(for循环处)设置断点,使用命令”b 30"。 (9)在33行(printf函数处)设置断点,使用命”b 33。 (10)查看断点设置情况,使用命令info b” (11)运行代码,使用命令“r”。 (12) 单步运行代码,使用命令“n”。 (13)查看暂停点变量值,使用命令”p string2[size-i]"。 (12)继续单步运行代码数次,并使用命令查看,发现string2[size-i]的值是正确的 (15)继续程序的运行,使用命令”c”。 (16)此时依次查看sting2[0]、string2[1]. . ,发现string[0]没有被正确赋值,而后面都是正确的,这时,定位程序第31行,发现程序运行错误的原因在于“size-1”,由于i只能增加到size-1,这样string2[0]就

相关主题
文本预览
相关文档 最新文档