在非ARC调用未声明的方法时,第一个参数为double会导致数据损坏。

时间:2014-04-16 23:25:38

标签: 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] init];
[objSomeClass methodWithDouble:21 andArray:nil];
[objSomeClass release];

您会注意到方法中的“ary”变为非零。如果内存指针属于某个其他对象,甚至可能会崩溃。

现在将“double”替换为“int”。这样可以正常工作。任何人都知道为什么......?

2 个答案:

答案 0 :(得分:3)

没有看到方法声明,编译器只能从参数中猜出方法签名,并且你已经21传递给它int,所以编译器猜它正在调用

- (bool) methodWithDouble:(int)value andArray:(NSArray*)ary

这是完全错误的,传递int和传递double的调用转换几乎总是不同的。调用者可以将4个字节推送到堆栈,而被调用者期望从堆栈中获取8个字节并将所有内容搞砸

如果您将21更改为21.0(加倍),则应该有效

答案 1 :(得分:3)

我想方法

- (bool) methodWithDouble:(double)value andArray:(NSArray*)ary

在编译时从您调用的地方

不可见
[objSomeClass methodWithDouble:21 andArray:nil];

所以编译器猜测第一个参数是int而不是使int(21)的隐式转换为double。如果你的架构' sizeof(int)!= sizeof(double)'第二个参数(nil)将不会放在" methodWithDouble:andArray:"所期望的那个位置。尝试将此行更改为

[objSomeClass methodWithDouble:(double)21 andArray:nil];

[objSomeClass methodWithDouble:21. andArray:nil];

更新:

一些澄清。

通过堆栈推送方法的参数。让我们假设

sizeof(int) == 4 
sizeof(double) == 8 
sizeof(void*) == 4 //pointers

因此,如果编译器使用参数(int,void *)调用某个方法,则会推送到4个字节用于int,4个字节用于指针。如果方法需要(double,void *),它会从堆栈中读取8个字节用于double(并接收错误的值),然后读取4个字节用于指针(并接收一些垃圾,因为只推送了8个字节)。