gdb查看内存地址和栈中的值

db查看指定地址的内存地址的值:examine 简写 x—–使用gdb> help x 来查看使用方式
x/ (n,f,u为可选参数)
n: 需要显示的内存单元个数,也就是从当前地址向后显示几个内存单元的内容,一个内存单元的大小由后面的u定义
f:显示格式
x(hex) 按十六进制格式显示变量。
d(decimal) 按十进制格式显示变量。
u(unsigned decimal) 按十进制格式显示无符号整型。
o(octal) 按八进制格式显示变量。
t(binary) 按二进制格式显示变量。
a(address) 按十六进制格式显示变量。
c(char) 按字符格式显示变量。
f(float) 按浮点数格式显示变量
u:每个单元的大小,按字节数来计算。默认是4 bytes。GDB会从指定内存地址开始读取指定字节,并把其当作一个值取出来,并使用格式f来显示
b:1 byte h:2 bytes w:4 bytes g:8 bytes
比如x/3uh 0x54320表示从内存地址0x54320读取内容,h表示以双字节为单位,3表示输出3个单位,u表示按照十六进制显示。

gdb打印表达式的值:print/f 表达式
f是输出的格式,x/d/u/o/t/a/c/f

表达式可以是当前程序的const常量,变量,函数等内容,但是GDB不能使用程序中所定义的宏

查看当前程序栈的内容: x/10x $sp–>打印stack的前10个元素
查看当前程序栈的信息: info frame—-list general info about the frame
查看当前程序栈的参数: info args—lists arguments to the function
查看当前程序栈的局部变量: info locals—list variables stored in the frame
查看当前寄存器的值:info registers(不包括浮点寄存器) info all-registers(包括浮点寄存器)
查看当前栈帧中的异常处理器:info catch(exception handlers)

来源

失落之城

书书

第一章 出发

我的奶奶从前是一名考古学家,在我很小的时候,她就跟我讲她考古时候的事,我很喜欢听。我从小听到大,也对奶奶口中讲述的失落之城充满了兴趣。

这天,镜子里扎着辫子,插着紫罗兰头花,长长的睫毛,有着挺挺的鼻子的我正坐在床上想象失落之城的种种神秘事件,突然,奶奶的声音从房间里传来:“黛娜,快点儿进来,我有话对你说。”“哦,我马上进来,奶奶。”于是,我三步并作两步冲进了房间,金色的卷发随风飘扬。奶奶的房间是这整个屋子里我最爱的,里面有一个大号的古铜色望远镜,一大串神秘的钥匙,老旧的墙纸上挂着一顶棕色的探险帽。在那靠着床边的小圆桌上有一个老旧的笔记本和一张神秘小岛的地图,一个布袋里还装着一个什么石头。奶奶对我说:“黛娜呀,我常跟你说的失落之城就是地图上的地方,这次,我希望你能带上布袋里的东西,”说着,奶奶就从袋子里拿出了一块闪闪发光的宝石,它是金色的爱心形状,形态美极了,一闪一闪的,亮得竟能从里面照到自己。我看呆了,我还从不知道奶奶有这种东西呢!

“拿上宝石,带上地图,准备好行李,去把这块宝石归还给失落之城,它才能恢复它原有的样子!”奶奶严肃地说道。“奶奶,您的意思是……呃……让我自己去岛里冒险,并把宝石归还回去?”“是的,黛娜,记得当年我们去探险,却把那个如此美丽而多样化的小岛搞得一团糟,所以,你要把它恢复原样。”“好的,奶奶,我会令您满意的!”我坚定地说道。奶奶那布满皱纹的脸上又溢满笑容:“黛娜,叫上你那几位爱探险的好朋友吧!有了你们几位,那座小岛一定会比以前更加生机勃勃的!”“嗯,我现在就去收拾行李,明天就出发!”

我回到房间里后,从衣柜里抽出一个很大的黑色旅行包,把要带的东西全部都拿了出来——春夏秋冬的衣服、洗漱用具,以及一个有蓝白相见花纹的大帐篷。收拾好这些东西之后,我走出房间,经过种有一大片紫罗兰的花园之后,来到了有无数川流不息的车辆经过的马路边。驶来了一辆公交车,正好可以到达我朋友的家门口。走上车,投了一枚硬币,随处找了一个座位坐了下来。

车子动了,我望向窗外,窗前的景物飞速般流去,所有东西都如五彩缤纷的水粉颜料一般流走了,只有新的事物扑面而来。到了,映入眼帘的是一幢拥有大花园的房子。走进用木栅栏围住的花园,一颗颗樱花树的花瓣掉在了人的身上,香气透人。地上种有三三两两的满天星,如白色星星般的小巧玲珑的小花缀在万绿丛中。我走到门前,墙壁上布满了美丽的玫瑰花,白色和粉色交织在绿色藤蔓中,很美。

我按了一下门铃,门打开了,映入眼帘的是一头棕色头发,大大眼睛,小小嘴巴的少女:“嗨,黛娜!快进来,今天你来有什么事吗?”“罗拉,我确实有事,”我说着进了门,她跑去冲了两杯咖啡,“就是我的奶奶叫我们去寻找她说的那个失落之城,并把这个,”我拿出了那颗宝石,“归还回去。请问你能跟我一起去吗?”’当然可以咯!你也知道……”她泯了一口咖啡,“我喜欢探险,对吧!”“好吧!你先收拾好行李,我去买船票,明天就出发!”

愉快的拜访结束了,我搭上公车去买船票,每个人都整装待发。第二天,晴空万里,我和罗拉搭上游轮,随着清凉的海风的伴随,我们向神秘小岛进发了!

未完待续……

堆和栈的区别

一、预备知识—程序的内存分配 

  一个由C/C++编译的程序占用的内存分为以下几个部分 
  1、栈区(stack)—   由编译器自动分配释放   ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。 
  2、堆区(heap)   —   一般由程序员分配释放,   若程序员不释放,程序结束时可能由OS回收   。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。 
  3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域, 程序结束后由系统释放。 
  4、文字常量区   —常量字符串就是放在这里的,程序结束后由系统释放 。
  5、程序代码区—存放函数体的二进制代码。 

    例子程序   

这是一个前辈写的,非常详细   
  //main.cpp   

 int   a   =   0;   //全局初始化区   
  char   *p1;   //全局未初始化区   
  main()   
  {   
  int   b;   //栈   
  char   s[]   =   "abc";  // 栈   
  char   *p2;  // 栈   
  char   *p3   =   "123456";  // 123456/0在常量区,p3在栈上。   
  static   int   c   =0;   //全局(静态)初始化区   
  p1   =   (char   *)malloc(10);   
  p2   =   (char   *)malloc(20);    // 分配得来得10和20字节的区域就在堆区。   
  strcpy(p1,   "123456");   //123456/0放在常量区,编译器可能会将它与p3所指向的"123456"  优化成一个地方。   
  }   

  二、堆和栈的理论知识   

  2.1申请方式   
  stack:   
  由系统自动分配。   例如,声明在函数中一个局部变量   int   b;   系统自动在栈中为b开辟空间   
  heap:   
  需要程序员自己申请,并指明大小。

\\在c中malloc函数如:
p1   =   (char   *)malloc(10);  
\\  在C++中用new运算符,如:
 p2   =   new   char[10];   \\但是注意p1、p2本身是在栈中的。    

2.2     申请后系统的响应   
  栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢   出。   
  堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。 
  另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。   

  2.3 申请大小的限制   
  栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。   
  堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。   
2.4申请效率的比较:   
 栈由系统自动分配,速度较快。但程序员是无法控制的。   
 堆是由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便。
 另外,在WINDOWS下,最好的方式是用VirtualAlloc分配内存,他不是在堆,也不是在栈是直接在进程的地址空间中保留一块内存,虽然用起来最不方便。但是速度快,也最灵活。 
2.5堆和栈中的存储内容   
 栈:   在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。   
当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。   
堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容由程序员安排。   

  2.6存取效率的比较   
  char   s1[]   =   “aaaaaaaaaaaaaaa”;   
  char   *s2   =   “bbbbbbbbbbbbbbbbb”;   
  aaaaaaaaaaa是在运行时刻赋值的;   
  而bbbbbbbbbbb是在编译时就确定的;   
  但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。   
  比如:   


  #include   
  void   main()   
  {   
  char   a   =   1;   
  char   c[]   =   "1234567890";   
  char   *p   ="1234567890";   
  a   =   c[1];   
  a   =   p[1];   
  return;   
  }   


  对应的汇编代码   
  10:   a   =   c[1];   
  00401067   8A   4D   F1   mov   cl,byte   ptr   [ebp-0Fh]   
  0040106A   88   4D   FC   mov   byte   ptr   [ebp-4],cl   
  11:   a   =   p[1];   
  0040106D   8B   55   EC   mov   edx,dword   ptr   [ebp-14h]   
  00401070   8A   42   01   mov   al,byte   ptr   [edx+1]   
  00401073   88   45   FC   mov   byte   ptr   [ebp-4],al   
  第一种在读取时直接就把字符串中的元素读到寄存器cl中,而第二种则要先把指针值读到edx中,再根据edx读取字符,显然慢了。   
2.7小结:   
堆和栈的区别可以用如下的比喻来看出:   
使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。   
使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。

Dev-C++中利用gdb查看内存地址中的值

Dev-C++中调用gdb

进行程序调试时我们可以看到调试框内有“ 发送命令到GDB ”这一项, 在此中输入命令,然后按回车即可调用GDB命令 。

Dev-C++中利用gdb查看内存地址中的值

  • 命令格式为
x/nfu <addr>

其中n,f,u为可选参数,为对应的内存地址

下面介绍这三个参数的作用

参数n-需要显示的内存单元个数

也就是从当前地址向后显示几个内存单元的内容,一个内存单元的大小由后面的u定义

参数f-显示格式

有时候我们希望数据内容以不同格式呈现,如2进制,16进制,修改f参数可以调整

x(hex)———————-按十六进制格式显示变量。
d(decimal)—————–按十进制格式显示变量。
u(unsigned decimal)—–按十进制格式显示无符号整型。
o(octal) ——————–按八进制格式显示变量。
t(binary)——————-按二进制格式显示变量。
a(address)—————–按十六进制格式显示变量。
c(char)———————按字符格式显示变量。
f(float) ——————–按浮点数格式显示变量

参数u-每个单元的大小,按字节数来计算

默认是4 bytes,GDB会从指定内存地址开始读取指定字节,并把其当作一个值取出来,并使用格式f来显示

b: 1byte

h: 2 bytes

w: 4 bytes

g:8 bytes

表达式可以是当前程序的const常量,变量,函数等内容,但是GDB不能使用程序中所定义的宏

举例使用

下面为示例代码,并在第5行处添加断点

#include<stdio.h>
int main()
{
    float d;
    d=8.25; 
    return 0;
}

在发送命令到GDB中输入如下代码

x/4xb &d

4代表输出4个内存单元

x代表以十六进制形式输出

b代表每个单元大小1个字节

输出内容如下

->->post-prompt
0x70fe1c:	0x00	0x00	0x04	0x41

则取得了变量d所在内存单元的十六进制数据

小猫打架记

妍妍

“哎哟!又打起来了!”

“快把四眼拉开呀!”

“快!快快!”

两只猫又打起来了!一只小花猫一只小白猫。它们俩先是发出怪叫声,那声音可真是震耳欲聋,响彻云霄!随后再各自冲上前,你抱着我,我抱着你,两猫都把爪子伸了出来,抱着对方的背,咬住对方脖子上的毛,再在地上滚几圈,直到双方都疼得受不了了才松开尖利的牙。

事情的原委是这样的:我家养了一只小猫叫咪咪,它的腿和肚子都是白色的,背上是黑色和白色组成的条纹,像穿了一件神气的马甲。它的眼睛可是非比寻常!一双眼睛又大又圆,黑白分明,眼珠是黄色的,光线强的时候会变成一条线,光线弱的时候也是圆圆的像玻璃珠。

这天,我们带着咪咪去了外婆家,外婆家有一只白猫,它的眼睛只有黄豆大小,全身雪白,只有眼睛上有两搓黑毛,就像有四只眼睛,所以外婆叫它四眼。四眼从来可都是独自吃好吃的,现在却来了一只猫,大概觉得自己的领地受到了侵犯,所以从咪咪来的第一天,它们俩就开始打架!

这边打架再次在大人们的喝骂声中结束了,四眼跑了,咪咪也吓得躲在椅子下面不敢出来,我们都不管了。晚上,夜深人静的时候,大家都睡熟了,四眼突然跑到门外,用猫语说着一些奇怪的话,听着有点儿像一个孩子在大声喊叫,我们都惊醒了,咪咪便也发出怪叫声儿,因为门是关着的,所以咪咪和四眼便隔着门在门下的缝隙里用爪子打架。四眼首先用爪子抵着门,咪咪看见了,便用爪子去狠狠地抓四眼的爪子。咪咪悄悄低下头,身子慢慢趴下,再一下子出击。四眼也毫不示弱,用怪叫声为自己助威,再一直抓,爪尖发出“滋”“滋”的声音。

它们就一直打,它们都永不停,虽然一直吵着我们,但它们一直都有一个坚持不懈的精神。