全局变量指针释放后未置空引发panic错误案例

本文介绍了一个因全局变量指针释放后未置空导致的panic错误案例。通过对错误现象、根本原因的详细分析,总结了解决方案及经验教训。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分类: C/C++

1、现象、问题描述
最近调试过程中,程序概率性出现Unable to handle kernel NULL pointer dereference at virtual address 访问空指针错误


2、关键过程、根本原因分析
最常见的两类panic错误如下:
Unable to handle kernel NULL pointer dereference at virtual address 访问空指针
Unable to handle kernel paging request at virtual address 访问不存在的地址
这两类错误都是_do_kernel_fault打印的,都是访问一个异常地址,区别只是访问大于PAGE_SIZE的就是paging request,小于PAGE_SIZE的就是NULL pointer dereference,PAGE_SIZE是4096,所以对这两种错误的定位流程是一样的。
这里采用objdump工具反汇编出错函数所在的.o文件导出分析

打开test.txt文件,搜索发生panic错误时提示的mcc_recvmsg_thread函数

根据搜索结果结婚发生错误时的mcc_recvmsg_thread+0x74/0x400信息计算出代码行0x1350-0x138+0x74=0x128c,继续搜索0x128c,得到结果

到对应的c文件中找到对应代码如下

可知在if(g_hi1610_dev_map[i]->vdd_checked_success != DEVICE_CHECKED_FLAG)发生了内存错误,于是在这里增加了判断后尝试复现,当if(NULL == g_hi1610_dev_map[i])时打印出g_local_handler全局变量的值用于定位。
g_local_handler全局变量初始化后的值如下:

当复现时抓取出g_local_handler全局变量的几个成员值如下:

可以看出,全局变量的成员值相比初始化后的数值已经被改写了,但是全局变量的指针地址没有变。于是开始了惨痛定位流程,尝试找出内存被踩的地方,但没有定位出来,最后进行代码走读,发现如下一段代码,在不定义MCC_PROC_ENABLE宏的情况下,函数会执行pci_register_drv_err及之后的代码,并且在释放g_local_handle指针后没有置NULL,这里有两个错误:一个是从业务层面看,正常执行时不应该执行pci_register_drv_err后的代码;一个是编程规范层面看,释放全局变量指针后需要置NULL。

3、结论、解决方案及效果
问题很低级,通过修改代码执行流程解决,当定位耗时较长,主要在于程序中使用了野指针导致定位时按照从内存被踩的角度出发,思路跑偏了。其实只要在平时写代码过程中牢记编程规范在释放全局变量指针后置空,这个问题就好定位出来了。

下图是在释放全局变量指针地址后置NULL重新复现的结果,可以看见在出错时有很明显的空指针提示,很容易指导定位
2025-06-30T17:08:41.317+0800 ERROR logger/logger.go:123 [Recovery from panic] {"error": "runtime error: invalid memory address or nil poi nter dereference", "request": "GET /lwh/v1/postListbyscore?Page=1&Size=10&Order=score HTTP/1.1\r\nHost: localhost:8001\r\nAccept: */*\r\nAccept-Enc oding: br, deflate, gzip, x-gzip\r\nAuthorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjo3MjY3MjIxNDU2NTYyNDYyNzIsInVzZXJuYW1l IjoiY2NnIiwiaXNzIjoibXktcHJvamVjdCIsImV4cCI6MTc4Mjc5NDEyM30.Oj4_dJBlIvzyk-Fi-LiwzxrmFHKhF2ynPJyPpNX0kqY\r\nUser-Agent: IntelliJ HTTP Client/GoLand 2025.1\r\n\r\n", "stack": "goroutine 12 [running]:\nruntime/debug.Stack()\n\tC:/Program Files/Go/src/runtime/debug/stack.go:26 +0x5e\nbluebell/rout er.Setup.GinRecovery.func2.1()\n\tC:/Users/linweihao/Desktop/study_go2/bluebell/logger/logger.go:126 +0x4d1\npanic({0x1699be0?, 0x29a6cd0?})\n\tC:/ Program Files/Go/src/runtime/panic.go:792 +0x132\nbluebell/logic.GetPostListByscore(0x161fca0?)\n\tC:/Users/linweihao/Desktop/study_go2/bluebell/lo gic/post.go:122 +0x43e\nbluebell/logic.GetPostListBy(0x9ccbc5?)\n\tC:/Users/linweihao/Desktop/study_go2/bluebell/logic/post.go:215 +0x27\nbluebell/ controller.GetPostList2Handler(0xc00058c600)\n\tC:/Users/linweihao/Desktop/study_go2/bluebell/controller/post.go:159 +0x1ee\ngithub.com/gin-gonic/g in.(*Context).Next(0xc00058c600)\n\tC:/Users/linweihao/go/pkg/mod/github.com/gin-gonic/gin@v1.10.1/context.go:185 +0x2b\nbluebell/router.Setup.JWTA uthMiddleware.func3(0xc00058c600)\n\tC:/Users/linweihao/Desktop/study_go2/bluebell/midwares/auth.go:39 +0x127\ngithub.com/gin-gonic/gin.(*Context). Next(0xc00058c600)\n\tC:/Users/linweihao/go/pkg/mod/github.com/gin-gonic/gin@v1.10.1/context.go:185 +0x2b\nbluebell/router.Setup.GinRecovery.func2( 0xc0006d76b8?)\n\tC:/Users/linweihao/Desktop/study_go2/bluebell/logger/logger.go:136 +0x47\ngithub.com/gin-gonic/gin.(*Context).Next(0xc00058c600)\ n\tC:/Users/linweihao/go/pkg/mod/github.com/gin-gonic/gin@v1.10.1/context.go
最新发布
07-01
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值