Ios 在非ARC中,对第一个参数为double的未声明方法的调用会导致数据损坏。
在非ARC中,对第一个参数为float的未声明方法的调用会导致不良行为 试试这个。使用以下方法创建一个类:Ios 在非ARC中,对第一个参数为double的未声明方法的调用会导致数据损坏。,ios,objective-c,Ios,Objective C,在非ARC中,对第一个参数为float的未声明方法的调用会导致不良行为 试试这个。使用以下方法创建一个类: - (bool) methodWithDouble:(double)value andArray:(NSArray*)ary { if (!ary) NSLog (@"Array is nil"); return true; } 现在调用该方法。为数组传入nil SomeClass *objSomeClass = [[SomeClass alloc] in
- (bool) methodWithDouble:(double)value andArray:(NSArray*)ary
{
if (!ary)
NSLog (@"Array is nil");
return true;
}
现在调用该方法。为数组传入nil
SomeClass *objSomeClass = [[SomeClass alloc] init];
[objSomeClass methodWithDouble:21 andArray:nil];
[objSomeClass release];
您将注意到方法中的ary变为非nil。如果内存指针属于其他对象,If甚至可能崩溃
现在将double替换为int。这将正常工作。谁知道为什么 如果不查看方法声明,编译器只能从参数中猜测方法签名,并且您已经向它传递了21,即int,因此编译器猜测它正在调用
- (bool) methodWithDouble:(int)value andArray:(NSArray*)ary
这是完全错误的,passint和passdouble的调用转换几乎总是不同的。调用者可能会将4个字节推送到堆栈中,而被调用者希望堆栈中有8个字节,这会把一切都搞砸
如果将21更改为21.0,则在不查看方法声明的情况下,它应该可以工作,编译器只能从参数中猜测方法签名,并且您已将21传递给它,即int,因此编译器猜测它正在调用
- (bool) methodWithDouble:(int)value andArray:(NSArray*)ary
这是完全错误的,passint和passdouble的调用转换几乎总是不同的。调用者可能会将4个字节推送到堆栈中,而被调用者希望堆栈中有8个字节,这会把一切都搞砸
如果您将21更改为21.0的两倍,那么它应该会起作用
- (bool) methodWithDouble:(double)value andArray:(NSArray*)ary
在编译时从调用的位置不可见
[objSomeClass methodWithDouble:21 andArray:nil];
所以编译器猜测第一个参数是int,而不是将int 21隐式转换为double。如果在您的体系结构“sizeofint!”sizeofdouble'第二个参数将不位于methodWithDouble:和Array:所期望的位置。试着把这行改成
[objSomeClass methodWithDouble:(double)21 andArray:nil];
或
更新:
一些澄清
方法的参数通过堆栈推送。让我们假设
sizeof(int) == 4
sizeof(double) == 8
sizeof(void*) == 4 //pointers
所以,若编译器使用int参数调用某个方法,void*会将int的4个字节和指针的4个字节推送到堆栈中。若方法需要double,则void*它从堆栈中读取double的8个字节,并接收错误的值,然后接收指针的4个字节,并接收一些垃圾,因为推送的位置只有8个字节
- (bool) methodWithDouble:(double)value andArray:(NSArray*)ary
在编译时从调用的位置不可见
[objSomeClass methodWithDouble:21 andArray:nil];
所以编译器猜测第一个参数是int,而不是将int 21隐式转换为double。如果在您的体系结构“sizeofint!”sizeofdouble'第二个参数将不位于methodWithDouble:和Array:所期望的位置。试着把这行改成
[objSomeClass methodWithDouble:(double)21 andArray:nil];
或
更新:
一些澄清
方法的参数通过堆栈推送。让我们假设
sizeof(int) == 4
sizeof(double) == 8
sizeof(void*) == 4 //pointers
所以,若编译器使用int参数调用某个方法,void*会将int的4个字节和指针的4个字节推送到堆栈中。如果方法需要double,void*它从堆栈中读取double的8个字节,并接收错误的值,然后接收指针的4个字节,并接收一些垃圾,因为只有8个字节被推送。运行此操作的硬件是什么?ARM还是x86上的模拟器?64位Mac上的64位模拟器,iOS 7.1 SDKAR您看到编译器警告了吗?如果没有,您是否已将其关闭?下面的两个答案都是可信的,应该给你一个警告。是的,我看到了警告。我在测试单元测试时遇到了这种情况,单元测试调用的方法未在SDK接口上公开。如果看到警告,请修复它们!你运行这个的硬件是什么?ARM还是x86上的模拟器?64位Mac上的64位模拟器,iOS 7.1 SDKAR您看到编译器警告了吗?如果没有,您是否已将其关闭?下面的两个答案都是可信的,应该给你一个警告。是的,我看到了警告。我在测试单元测试时遇到了这种情况,单元测试调用的方法未在SDK接口上公开。如果看到警告,请修复它们!但是如果NSARAY没有以零的形式通过呢?相反,它带有一个内存指针。当我通过21.0考试时,NSArray的成绩为零。int/double answer的Upvote将以nil通过,但未正确读取。请稍等,我将更新答案。方法的参数可以通过寄存器传递。即使double和long具有相同的大小,也可能会得到错误的结果,但是NSArray不作为零传递又如何呢?相反,它带有一个内存指针。当我通过21.0考试时,NSArray的成绩为零。int/double answer的Upvote将以nil通过,但未正确读取。请稍等,我将更新答案。方法的参数可以通过寄存器传递。即使双倍的和长的有相同的尺寸,它仍然可能得到错误的结果