(新人第二帖)循环链表建立,连接操作中的怪异bug分析与解决(C语言实现)

博客详细分析了一位程序员在使用C语言实现循环链表遍历和合并过程中遇到的指针错误。主要问题是malloc操作导致头节点地址改变,造成野指针访问,以及在合并链表时不必要的指针赋值导致的循环链表闭环失败。解决方案包括将malloc操作移至主函数和删除不必要的指针赋值。通过调试和理解指针行为,成功解决了程序崩溃和输出异常的问题。
摘要由CSDN通过智能技术生成

问题概述:
这是我在前一天晚上拿到手的问题.程序员想利用c语言实现循环链表的遍历和简单的连接操作(直接将一个链表插入另一个链表后面,不进行边插入边比较的操作).原程序较为复杂,有很多当时还没来得及调试和使用的函数,在此按下不表.本文只讨论我接到程序时主函数中用过的函数.
出错现象为无法输出任何数据,主函数返回值异常.这是c/c++中最为常见的错误之一,基本上都和指针访问密不可分.考虑在总览程序之后使用单步调试定位出现异常的指针操作并予以修改.
工具:Visual Studio Code,扩展包包括code runner,c/c++常用扩展等.通过命令行指令确定了编译器已经正确安装并配置.
具体分析:
第一个问题:
插入节点的例程.
在这里插入图片描述
合并链表的例程.定位到第一个链表的尾节点,然后让其next指针指向第二个节点头节点后的第一个节点,再把第二个链表的尾节点next指针指向第一个链表的头节点.思路还是比较清晰的.
在这里插入图片描述
主函数.使用两个数组进行测试.(这里表扬一下编程者写中文注释的习惯QAQ)
运行该程序,发现只输出ha: 程序就卡死,没有任何输出并最后强制终止运行.初步判断createlist函数存在问题,应该是野指针访问.断点设置在createlist前,在单步调试.
问题出现了:
在这里插入图片描述
在这里插入图片描述
主函数中ha为0x991530,刚传入函数时也正常.函数欲使这个ha成为链表的头节点,对其分配空间,**但是malloc这句话运行过后,发现L变成了0x991600.**之后的代码没有问题,L的每个节点值都是对的.但是这些值,节点都是以0x991600为开始地址进行排列的,主函数中0x991530地址则没有被操作,成为了野地址.因此返回主函数之后再从ha开始做DispList操作,则成为了野地址访问,程序出现这种令人不解的bug也就十分合理了.
由于调试发现malloc之后地址发生变化,考虑将malloc放进主函数,等内存分配完成之后在进入函数,即可避免该问题.再次调试运行,ha,hb都能正常输出.
第二个问题:
链表合并之后,hc不能正常输出.
在这里插入图片描述
输出的是大量怪异值.将断点放到mergelist函数之前,进行单步调试,发现lc=la一句话之后,lc的next指针为野值.因此,这个问题的发生还是野指针访问.
如果我们继续调试,在displist函数中会报错segmentation fault,应证了我们的判断.
解决方式:再仔细阅读mergelist函数之后,不难发现这里的lc(对应主函数中hc)是完全多余的.合并之后la已经成为了新循环链表的头节点,主函数中直接输出la即可.最好的解决方式是去掉lc=la这句话,去掉参数表中的lc,去掉主函数中的hc.
这里的lc=la到底犯了什么错误?我认为,原因在于这句话只是单纯的指针赋值,将la指针的值赋给了,而lc的内容却是空的.回到主函数,发现hc根本就没变!(更别说next指针还是野的)
在这里插入图片描述
那能不能改成*lc=*la?这样使得两个指针指向的对象一样,lc就能得到la的正确的next指针值,后面不是就可以一顺下去,把所有next指针都弄对?事实确实是这样.但是,当这种一顺下去的赋值进行到尾节点时,它会将next值设置为la的地址.这是十分合理的,因为这就相当于la链表向lc链表的拷贝.而这里la的地址和lc的地址是不一样的,也就是说,lc链表的尾节点next指针没有指向lc,而是指向了la!!!这个新建立的循环链表根本没有闭环,运行displist函数会造成死循环!!!
在这里插入图片描述
在这里插入图片描述
如图所示.
有的不信邪的朋友可能非要问了:我就要用这个lc和hc,怎么办?
办法还是有的.无非是想让hc也是链表头节点而已,指针赋值嘛,传二级指针就行.将mergelist函数的参数表中 *lc 改为 **lc,lc = la 改为 *lc=la,主函数调用合并函数时hc改为&hc.但是这样未免多此一举,效果跟上面提到的最好的解决方式一模一样,还颇费周折,直接输出ha不是更方便吗?
至此这个问题和其衍生问题应该都差不多了,小白能力有限,还希望各位大佬批评指正,提出改进意见!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值