Linux学习----gdb调试(指针的指针)
昨天遇到一个很奇怪的问题,如下:
按照理论,最后*p的值应该是99,不知为什么是15了,所以今天记录用gdb调试的过程,并熟悉gdb的使用。
(调试过程参考:http://www.cnblogs.com/hankers/archive/2012/12/07/2806836.html)
开始:
1.
2.(用list从第1行开始列出源码)
3.(一次只列10行,如果要从第11行开始继续列源代码可以输入list)
4.(也可以什么都不输直接敲回车,gdb
提供了一个很方便的功能,在提示符下直接敲回车表示重复上一条命令。)
5.(gdb
的很多常用命令有简写形式,例如list
命令可以写成l
,要列一个函数的源代码也可以用函数名做参数:)
6.(退出gdb环境)
7.(现在将niuke.cpp改名,然后gdb就列不出源码了)
说明:gcc
的-g
选项并不是把源代码嵌入到可执行文件中的,在调试时也需要源文件。
8.(源码文件恢复,重新开始)
gdb
停在main
函数中变量定义之后的第一条语句处等待我们发命令,gdb
列出的这条语句是即将执行的下一条语句。
9.(我们可以用next
命令(简写为n
)控制这些语句一条一条地执行)
说明:用n函数f()中的结果一下就打印出来了
10.(现在用start重新开始,用step命令(简写s)进入f()中去跟踪执行)
现在进入了f()函数。
11.(在函数中有几种查看状态的办法,backtrace
命令(简写为bt
)可以查看函数调用的栈帧)
可见当前f()是被main()调用的,传入指针p传给ret=0xbfffee94
12.(查看当前f()函数内局部变量的值i locals 或者info locals)
13.(如果想查看main
函数当前局部变量的值也可以做到,先用frame
命令(简写为f
)选择1号栈帧然后再查看局部变量,i locals, info locals)
14.(继续运行,然后用p+变量名查看变量的值)
这里......$5,$6,$7,$8......分别保存了查看的中间值:
未执行*ret = &a时:
ret: 0xbfffee94(为&p) *ret:0xbfffef54(p) **ret:-1073745577
执行*ret = &a后:
ret: 0xbfffee94 *ret:0xbfffee68 = &a:0xbfffee68(值为99) **ret:99(等于a)
15.(finish命令让程序一直运行到当前函数结束)
返回值是ret=0xbfffee94(&p)
16.(现在继续运行)
注意:A &p address : 0xbfffee94(&p未改变) A p address : 0xbfffee68(与&a相同) A *p value : 15(奇怪的地方,为什么不是99)
17.(换一种思路:在执行 cout << "A &p address : " << &p << endl; 之前直接查看*p)
这里可以看到*p=99,是正确的,地址也与上面相同
18.(继续调试)
这里发现*p=15,被改变了。
也就是说:在执行cout << "A &p address : " << &p << endl;后, *p的值被改变了,从99变为15了。
19.(连续输出两次*p)
这次发现第一次输出结果正常,第二次输出结果出错,那为什么呢?为什么呢?????
20.(知道原因了)
- 说明:a是一个局部变量,&a在f()执行完后就被系统回收了。f()中ret = &a 这一步,使得p=&a,所以最后p输出不对。
修改后:
这里终于正确了。
PS:前面一种情况,栈被系统回收,但是仍能输出一次99,我猜可能是系统还没来的及回收。。。
PSS:指针太容易出错了。。
Linux学习----gdb调试(指针的指针)的更多相关文章
- Linux学习--gdb调试
一.gdb常用命令: 命令 描述 backtrace(或bt) 查看各级函数调用及参数 finish 连续运行到当前函数返回为止,然后停下来等待命令 frame(或f) 帧编号 选择栈帧 info(或 ...
- Linux知识(5)----LINUX下GDB调试
命令 解释 示例 file 加载被调试的可执行程序文件.因为一般都在被调试程序所在目录下执行GDB,因而文本名不需要带路径. (gdb) file gdb-sample r c Run的简 ...
- 一文入门Linux下gdb调试(二)
作者:良知犹存 转载授权以及围观:欢迎添加微信号:Conscience_Remains 总述 今天我们介绍一下core dump文件,Core dump叫做核心转储,它是进程运行时在突然崩溃的 ...
- Linux学习——Gdb基本调试方法&&多线程调试
1.Gdb的基本调试 示例代码 //e.c #include <stdio.h> void debug(char *str) { printf("debug info :%s\n ...
- Linux+eclipse+gdb调试postgresql源码
pg内核源码解析课上用的vs调试pg源码, VS用起来确实方便,但是配置调试环境着实有点麻烦.首先得装个windows系统,最好是xp,win7稍微麻烦点:最好使用vs05,08和10也可以,但是比0 ...
- Linux下GDB调试简单示例
这里介绍对文件first.c的基本GDB调试操作,只有部分命令,只是一个示例,运行环境为装有gcc编译器和gdb调试器的Linux环境,基本GDB调试命令如下表: 命令 ...
- (十五)linux下gdb调试
一.gdb常用命令: 命令 描述 backtrace(或bt) 查看各级函数调用及参数 finish 连续运行到当前函数返回为止,然后停下来等待命令 frame(或f) 帧编号 选择栈帧 info(或 ...
- Linux嵌入式GDB调试环境搭建
======================= 我的环境 ==========================PC 端: CPU:x86_64, 系统:Ubuntu,IP:172.16.2.212开发 ...
- 一文入门Linux下gdb调试(一)
作者:良知犹存 转载授权以及围观:欢迎添加微信号:Conscience_Remains 总述 在window下我们习惯了IDE的各种调试按钮,说实话确实挺方便的,但到了Linux下,没有那么多的IDE ...
随机推荐
- Windows server 2012配置WebDeploy发布网站
以前都是使用win2008r2服务器,最近更新了操作系统到WINDOWS 2012,发现以前的做法已经不适用了. win2008r2配置WebDeploy: https://www.cnblogs.c ...
- C++设计模式——外观模式
前言 在实际开发时,面对一个大的系统,总是会将一个大的系统分成若干个子系统,等子系统完成之后,再分别调用对应的子系统来完成对应的整体功能,这样有利于降低系统的复杂性:最终进行实现某个具体的功能时,我们 ...
- 【原创】大数据基础之Spark(2)Spark on Yarn:container memory allocation容器内存分配
spark 2.1.1 最近spark任务(spark on yarn)有一个报错 Diagnostics: Container [pid=5901,containerID=container_154 ...
- 在浏览器中查看.vue文件的源码
- unity 使用方法
1.Rotaion 想要设定一个实例的rotation的时候不能使用Vector3来直接设定:应改为 rotation = Quaternion.Euler (0.0f, 180.0f, 0.0f); ...
- ubuntu服务器上提示 To run a command as administrator (user "root"), use "sudo <command>". See " 解决方案
原因是你执行命令必须要在root用户下执行.其他用户权限不够.运行 sudo -s 切换到root用户下就可以了
- springboot配置文件priperties大全
flyway.baseline-description 执行基线时标记已有Schema的描述. flyway.baseline-on-migrate 在没有元数据表的情况下,针对非空Schema执行迁 ...
- Vertx.vertx()初始框图和模块
Vertx.vertx()实例 一.构造方法 1. VertxImpl构造方法 选择 transports protocol , default select 模型 if (options.getPr ...
- python第10天(下)
https://www.cnblogs.com/zingp/p/6863170.html 一:IO模型介绍 IO发生时涉及的对象和步骤 对于一个网络IO(network IO),它会涉及到两个系统对 ...
- C#学习-子类的初始化顺序
使用了继承之后,当我们初始化一个子类时,除了会调用子类的构造函数外,同时也会调用基类的构造函数. 子类的初始化顺序如下: (1)初始化类的实例字段: (2)调用基类的构造函数: (3)调用子类的构造函 ...