3

CGRect を NSInvocation (setArgument:atIndex:) に渡そうとします。NSValue でラップし、NSArry にプッシュしてから、NSArray から取得し、NSValue (getValue:) を使用します。(getValue:) メソッドを呼び出すと、宣言前のインデックス NSInteger i が変更されます。なぜこれが起こるのか誰にも言えますか?

 NSString className = @"UIButton";
    Class cls = NSClassFromString(className);
    cls pushButton5 = [[cls alloc] init];
    CGRect rect =CGRectMake(20,220,280,30);
    NSMethodSignature *msignature1;
    NSInvocation *anInvocation1;

    msignature1 = [pushButton5 methodSignatureForSelector:@selector(setFrame:)];
    anInvocation1 = [NSInvocation invocationWithMethodSignature:msignature1];

[anInvocation1 setTarget:pushButton5];
[anInvocation1 setSelector:@selector(setFrame:)];
NSValue* rectValue = [NSValue valueWithCGRect:rect];
NSArray *params1;
params1= [NSArray arrayWithObjects:rectValue,nil];
id currentVal = [params1 objectAtIndex:0];
NSInteger i=2;
if ([currentVal isKindOfClass:[NSValue class]]) {
    void *bufferForValue;
    [currentVal getValue:&bufferForValue];
    [anInvocation1 setArgument:&bufferForValue atIndex:i];
}else {
    [anInvocation1 setArgument:&currentVal atIndex:i];
}
[anInvocation1 invoke];

この(getValue:)メソッドが 'i' の値を 2 から 1130102784 のような値に変更すると、(setArgument:atIndex:)インデックス i が範囲外であるため、SIGABRT が発生します。

では、なぜ は[NSValue getValue:(*void) buffer]他の変数を変更するのでしょうか?

(PS関数でそれを行うので、例を単純化して配列を直接初期化します。そして、直接atIndex:2を設定すると、完全に機能します。しかし、悲しいことに、少し単純化し、iをatIndexに渡す必要があります: )


Tom Dalling (特に) と sergio の問題が解決したおかげです。これを削除します:

void *bufferForValue;
[currentVal getValue:&bufferForValue];
[anInvocation1 setArgument:&bufferForValue atIndex:i];

これを貼り付けます

NSUInteger bufferSize = 0;
NSGetSizeAndAlignment([currentVal objCType], &bufferSize, NULL);
void* buffer = malloc(bufferSize);
[currentVal getValue:buffer];
[anInvocation1 setArgument:buffer atIndex:i];

ありがとうございました。Stackoverflow.com は、頭の良い人がいる本当に役立つサイトです。

4

2 に答える 2

10

NSRectを に適合させることはできませんvoid*。正しいコードは次のようになります。

NSRect buffer;
[currentVal getValue:&buffer];

NSValueまたは、オブジェクトの内容がわからない場合は、次のようにします。

NSUInteger bufferSize = 0;
NSGetSizeAndAlignment([currentVal objCType], &bufferSize, NULL);
void* buffer = malloc(bufferSize);
[currentVal getValue:buffer]; //notice the lack of '&'
//do something here
free(buffer);

iコードが他のスタック割り当て変数へのオーバーフローを引き起こすため、の値が変化しています。

于 2011-08-12T07:17:40.833 に答える
3

の:

 void *bufferForValue;
 [currentVal getValue:&bufferForValue];

(ポインタ)currentValのサイズを持つバッファに値をコピーしています。void*今、参照をgetValue参照してください:

取得値:

レシーバーの値を特定のバッファーにコピーします。

バッファ

レシーバーの値をコピーするバッファー。buffer は、値を保持するのに十分な大きさである必要があります。

バッファにコピーする値は a に収まらないためvoid*、ローカル変数のアドレスに書き込んでいるため、スタックを上書きしています。これはおそらくiローカル変数を上書きする効果があるため、何が起こっているのかを説明しています。

于 2011-08-12T07:13:26.453 に答える