win732位正常64位外部组件发生异常_记64位地址截断引发的挂死问题

924185814d6318e27bf8316b46b2ed9a.png

关注后你就是我的人了

前言

最近要将整个项目的代码从原先的只支持32位变成同时支持32位和64位,这个过程中遇到一个很不容易定位的挂死问题,花了不少时间才定位解决,因此分享给大家。

32位和64位代码区别

在分享之前,需要了解一下32位和64位程序代码有何区别,它的主要区别体现在某些数据类型的占用字节大小的不同:

数据类型32位64位long4字节8字节unsigned long4字节8字节指针4字节8字节size_t4字节8字节ssize_t4字节8字节

这些是主要的差别。

那么为什么要切64位呢?原因也很简单,32位寻址范围有限,能使用的最大内存也是非常有限的,因此需要使其能够支持64位,这个过程需要修改编译工程,编译第三方库为64位,修改代码等等。当然这些都不是本文的重点,本文仅介绍遇到的这个典型的问题。

问题描述

由于项目本身涉及的系统比较复杂,因此简单分享一下定位过程,下一节将通过简洁的示例程序来说明。

问题现象:向服务器发送一条操作指令后直接挂死

分析解决过程简化为如下步骤:

  • 查看日志以及coredump信息,初步定位挂死的位置
  • 发现挂死在停止定时器的位置
  • 32位程序正常,而64位异常,因此和32位与64位的差别有关
  • 怀疑传入定时器数据有问题,编写小demo,排除传入数据问题
  • 编译可调试版本,加入-g参数
  • 跟踪调试,发现最终挂在了一个动态库中
  • 设置gdb源码路径,以便调试跟踪动态库
  • 通过gdb观察传入指针,在访问指针时,出现错误,提示访问非法内存
  • 打印传入定时器指针地址,发现异常,地址开头4字节为全f,不正常,因此怀疑该指针最开始就已经出问题
  • 跟踪启动定时器部分,动态库接口返回的地址值,就已经异常了。但是跟踪到动态库接口内部,发现返回的结果是正常的8字节地址值,排除定时器接口的问题
  • 最终可以确定,在调用动态库接口时,虽然返回的是8字节地址,但是赋给外部变量时,就被截断
  • 换项目中的另外一个进程调试demo发现,编译时出现错误,提示函数没有声明
  • 于是加上声明之后编译通过,但并没有出现挂死的问题
  • 随即继续跟踪原项目出问题的进程,发现同样这些接口都没有外部声明,再加上另外一个进程的警告信息,提示有int往指针强转,因此怀疑和函数的声明有关。

最终确实如此。

具体是为什么呢?

简化示例

示例代码分别放在main.c和test.c中,main.c内容如下:

//main.c//公众号编程珠玑#include#includeint main(void){ void *p = NULL; //打印p的地址 printf("%p
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值