32位CPU(iPhone5)出现的NSInteger溢出问题

在我们的APP中,有一处地方展示的是“生日”,这个生日数据是请求服务器返回的数据,在上一个版本发布之后陆续地有用户反馈说每次修改完生日就变成了1969年或1970年的日期,与后台的哥们沟通了之后发现,APP传给服务器的参数有时候甚至可能是负的(参数是毫秒数)。

那一天我们几乎花了一整天的时间去复现这一个Bug,然而并没有找到原因,直到下午五点……

我提出了一个问题:“是不是特定的那几个用户总是出现这个问题,而别的用户没有出现?”,随后通过后台统计数据发现,出现了这个问题的用户使用的手机都是iPhone5,系统版本有iOS8也有iOS9。

OK,定位到了问题所在就容易解决啦。我们的测试机是一台iOS8的iPhone5s和一台iOS9的iPhone5s,同事们以及本人的手机不是iPhone6就是iPhone6s,我们都没有遇到这个问题,并且所有的非iPhone5用户也没有出现这个问题,这样看来问题应该就出在iPhone5上。

仔细想了一下,苹果在iPhone5s上开始使用64位的CPU,而在iPhone5以及更老的iPhone上使用的一直都是32位的CPU,会不会是这个原因?

为了验证是否真是这个原因,在xcode中运行APP的时候我选择了iPhone5模拟器,果然!随后按住Command键点击NSInteger发现NSInteger的定义是这样的。

#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
typedef long NSInteger;
typedef unsigned long NSUInteger;
#else
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif

苹果在32位的机子上将NSInteger定义为了int类型,而在64位机子上定义为long类型(int类型在存储现在的毫秒数的时候当然会溢出啦)。

既然问题找到了,那就开始解决吧~原本想着手动将用到NSInteger来记录毫秒数的变量改成long类型,但是发现需要改的地方很多。想到我们的项目中有一个pch文件,于是在pch文件中写了这么一行代码

#define NSInteger long

机智如我哈哈哈

等等,保险起见还是得再编译运行一次看看。唉?怎么还是1970年?这不科学啊!!!

继续查阅了一下资料后发现,原来32位跟64位的基本数据类型还是有区别的

int long long long
32位CPU 32bit 32bit 64bit
64位CPU 32bit 64bit 64bit

也就是说,在iPhone5上,int跟long类型其实是等同的,都是32bit,而在iPhone5s上long类型与long long类型是等同的,都是64bit。于是将pch文件中的宏定义修改了一下。

#define NSInteger long long

编译运行,OK,问题解决~机智如我~

等等,这满屏幕的warning是怎么回事???(╯‵□′)╯︵┻━┻

小结

毕竟本人懒癌晚期,这种方法简单粗暴,但会让你的项目到处都是warning,强迫症患者慎用!!!如果有更好的解决方法(只要不是手动将需要NSInteger替换成long long)请告诉我~

点赞
  1. Mohammad04说道:

    I think your page needs some fresh posts. Writing manually takes a lot of
    time, but there is tool for this boring task, search for:
    Boorfe's tips unlimited content

发表评论

电子邮件地址不会被公开。 必填项已用*标注