Linux系统编程.NO8——gdb、内存与指针

6.C语言指针与内存

6.1.gdb调试工具

编写完.c代码后,编译时候加上-g参数,如gcc -g mun -o mun.c,得到的可执行文件就可以通过gdb工具进行调试。
命令gdb+可执行文件,进入gdb交互模式,按L键可以列出部分源代码,再按就继续显示后面的。按回车表示继续执行上一次的命令,命令break+行号可以在该行设置断点,命令start开始调试代码,命令p+变量名,就可以打印出当前变量的值,p(printf)。命令n键,就跳到下一行,n(next).输出的$1,$2等表示输出的第几个变量。遇到函数的时候,命令s键进入函数内部。命令bt查看函数堆栈,堆栈根据不同的作用于显示,最上面的就是当前进行的堆栈函数。不同函数的堆栈前有代表该函数的编号#0,#1等,使用命令f+函数编号,就可以跳转到该函数中去,进入该函数栈空间。命令q键退出交互界面。命令x/nh+内存地址,x/是格式,n是个数,表示从该内存地址开始连续显示n个值,也就是该地址保存的值,还有下一个地址所保存的值,一直到第n个,h表示显示进制,d表示10进制。

6.2.内存概念

对于32位操作系统,它的地址总线是32位,也就是寻址空间是32位,也就是给内存的标号最多只能由32位,由于计算机是使用的2进制编码,所以最多只能有32个二进制位。所以一共只有2^32 种状态,所以只能存储2^32 个字节。64位操作系统的理论上可管理的空间就是2^64 。每个字节的内存都保存一个byte,也就是一个8位的二进制数。在当今64位操作系统中,操作系统虽然理论上可操作空间是2^64 位,但是实际上一般只认为2^48位是有效的,也就是0x7ffff…f一直到0x0。而0x7ffff一直到0xffff…f的内存空间是给操作系统内核使用的。这样可以保证操作系统的内存不会被用户进程来占用。

6.3.变量和指针的本质

C语言语法不允许操作代码段,代码执行的过程中产生的过程量都被保存在栈空间当中。
变量的本质就只是一个代号,它代表了一个地址空间,真正重要的是这个地址空间所保存的值,而变量被声明后,在编译过程中都被保存在栈空间。变量的作用就是告诉cpu,这个值需要到哪个地址去取得。
指针保存的就是内存地址,指针首先一旦被定义,指针本身也是一个变量,当指针p被赋值后,如int *p=&a,直接打印p,得到的是a的内存地址,而打印**p或者&p才是p本身所在的地址,所以实际上p本身还有一个地址。

6.4.操作系统对内存的管理

64位操作系统的指针就一定是占8个地址,只要是指针,就一定占8个字节,因为指针是指向一个地址,一个地址是64位,所以一个指针必须是64位,和其指向的对象无关,即使是指向一个函数的指针,也是8个字节。
如果在代码中定义了很多变量,那么在执行的时候,编译器会按照不同类型的变量依次分配栈空间的内存给这些变量。而每次调用一个函数就会分配一个新的栈空间,所以栈空间就是不确定的一个空间。

6.5.函数栈以及数据段内存

数据段或者代码段的内存分配都是从下往上分配,因为代码一旦写好,系统就明确知道这两部分的大小,就会从下往上分配内存。
而栈空间则是从上往下分配,因为代码在执行的过程中一个栈空间有多大系统事先是不知道的,所以就从最上面开始分配,所以在一个c语言代码中。第一个栈空间就是main函数的栈空间,并且给它分配的栈空间首地址就是可分配栈空间地址的最高地址。也正是由于栈空间从上往下分配,所以栈空间的释放也只能是先入后出,也就是后生成的栈空间要先关闭,这样也符合代码执行逻辑,第一个生成的栈空间是main函数的栈空间,肯定是要最后一个释放的。

6.6.函数指针与指针指向的数据访问

函数名本身也是存在某个地址,只不过保存在一段代码段的地址,而且不能直接使用函数名做变量,但是这不影响它是一个地址的情况,使用函数指针如(*strcpy),*表示读出指针所代表的值,如果指针是一个函数,那么就是指向在代码段的这一段代码,str3=(*strcpy)(str1,str2)就表示对str1和str2调用了strcpy函数,也就是说函数指针指向的是函数本身的内容,而作用就是调用这个函数。

6.7. 指针运算

指针的加减运算不能改变指针所指向的值,而是在地址上的加减,具体加减多少个字节取决于定义指针时候的类型,所以虽然指针类型不能决定指针大小,但是可以决定指针移动时的单位。
当定义一个数组时,数组内各个元素也会被挨个排列在内存中,而数组角标的++实现的结果和指针的++得到的结果是一样的,所以定义一个指针一定程度上也就是定义了一个数组,数组名就是指针名,可以直接加角标。
理论上所有数组的操作都可以通过指针来实现,但是所有指针的操作不一定能由数组来决定。数组和指针最大的不同在于,一个指针是没有范围的,而一个数组是有范围的,所以将一个数组看做一个指针那么该指针就被限定在一个小范围内,这样来说就相对更加安全。所以一般的指针就是一个动态指针,而一个数组可以看做一个一定程度上的静态指针,所以静态指针范围更小,功能更少,但是更加稳定、安全。

6.8.内存空间分布

在可用的地址空间,一般也被划分成各种功能:
在这里插入图片描述
在这里插入图片描述
BSS:用于存放程序中未初始化的全局变量的一块内存,静态内存分配。
数据段:存放已初始化的全局变量的一块内存区域,静态内存分配。
代码段:存放执行代码的一块内存区域(只读区域,字符串常量也属于代码段)。
堆(heap):存放进程中被动态分配的内存段,不固定,可动态扩展或收缩。
栈(stack):存放局部变量,传递参数和返回值,先入先出。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值