刚接触指针的时候,经常会遇到段错误。
root@turbo:linklist# lslink.c link.h main main.croot@turbo:linklist# ./main链表初始化成功segmentation fault (core dumped)root@turbo:linklist#所谓段错误,就是访问了不能访问的内存。
比如内存不存在,或者受保护等等。 遇到段错误,就得去调试,不管是通过什么手段,一定得先找到哪行代码出现了段错误,然后才能分析修改。
调试段错误的手段很多,对于初学者,我推荐两个,一个是通过打印的方式定位,一个是使用gdb。 打印方法最简单。 root@turbo:linklist# lslink.c link.h main main.croot@turbo:linklist# ./main链表初始化成功segmentation fault (core dumped)root@turbo:linklist#比如这里有个链表的代码,代码量大概300行,从现象可以看出,链表的初始化成功,紧接着就出现了段错误。 于是我们大概能推测出问题出在了链表的插入操作上。int insert_link(node *h, int p, int n){ if (null == h) { return failure; } //把指针移动到要插入位置的前一个位置 node *q = h; int k = 1; while (k next; k++; } //判断位置是否合法 if (q == null || k > p) //位置太大 位置太小 { return failure; } node *m = (node *)malloc(sizeof(node) * 1); if (null == m) { return failure; } m->data = n; m->next = q->next; q->next = m; return success;}找到链表的插入操作,可以把它分成几个功能,入参判断,移动指针,判断位置是否合法,申请新节点,修改指针域。
在每个功能前面加上一些打印,随便打印什么都行。int insert_link(node *h, int p, int n){ //printf(1111); if (null == h) { return failure; } //printf(2222); //把指针移动到要插入位置的前一个位置 node *q = h; int k = 1; while (k next; k++; } printf(3333); //判断位置是否合法 if (q == null || k > p) //位置太大 位置太小 { return failure; } printf(4444); node *m = (node *)malloc(sizeof(node) * 1); if (null == m) { return failure; } printf(5555); m->data = n; m->next = q->next; q->next = m; return success;} 再次运行,程序输出了1和2。root@turbo:linklist# gcc main.c link.c -o mainroot@turbo:linklist# ./main链表初始化成功11112222segmentation fault (core dumped)root@turbo:linklist#于是,问题再次被缩小,应该是移动指针的时候出了问题。//把指针移动到要插入位置的前一个位置 node *q = h; int k = 1; while (k next; k++; }这几行代码,能跟指针扯上关系的,应该就是第 6 行了。当然,这只是发现了段错误在哪,具体怎么修改,还得根据你的业务逻辑继续分析。
通过打印定位问题确实比较慢。如果代码量比较大,又不能大概判断出问题所在,可以借助一些工具,常用的比如gdbroot@turbo:linklist# gcc main.c link.c -o main -groot@turbo:linklist# gdb maingnu gdb (ubuntu 9.2-0ubuntu1~20.04.1) 9.2copyright (c) 2020 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 x86_64-linux-gnu.type show configuration for configuration details.for bug reporting instructions, please see:.find the gdb manual and other documentation resources online at: .for help, type help.type apropos word to search for commands related to word...reading symbols from main...(gdb) runstarting program: /root/test/linklist/main 链表初始化成功11112222program received signal sigsegv, segmentation fault.0x0000555555555783 in insert_link (h=0x5555555592a0, p=5, n=9) at link.c:4242 q = q->next;(gdb)编译的时候加上-g选项,直接使用gdb加上文件名,run启动程序,一眼就能看出错误在第42行。
当然了,这个程序是我故意写的段错误,有些段错误发生在库里面,并不能很直观的看出来在哪一行。这就需要借助断点、单步调试等等操作。
类似gdb的调试工具还有很多,如果是初学者,没必要掌握太多,能解决问题就行。
戴尔近期与私募基金接触 预计出售旗下所有软件事业
COMBICON 50年:解锁PCB连接技术的成功密码!文末有惊喜~
最薄的光学器件:一种只有三层原子厚的波导
SpaceX星际飞船顺利完成首次静态点火测试
英特尔加速基于RISC-V内核的处理器和SoC开发
段错误是什么意思?是何原因引起的?
NokiaX5评测 在各方面表现都十分均衡
面板产业充满挑战,台厂与LED厂合作新显示技术
本田采用3D打印技术打造零部件 实现了车身零部件的轻量化
利用AI人工智能技术将普通常见的30fps进行智能插帧计算获得240/480fps的慢动作视频
Intel不再提供新的PTPP超频保险服务
华为nova5 Pro搭载了麒麟980处理器将于7月20号正式开售
糖果手机是谁?"学外语,就用糖果翻译手机"
FPGA设计实战-复位电路仿真设计
小米MIX2来了:100%屏占比,对手只有iPhone8!
利用神经网络识别追踪实验特征
Agilent FieldFox脉冲测量能够简化雷达现场测试
低频段5G网络的优缺点分析
吉时利源表常见型号及故障分享|安泰维修
电子文件隐藏存储的方式有哪些