簡體   English   中英

NSInvocation getArgument NSString/CFString 會導致訪問錯誤

[英]NSInvocation getArgument NSString/CFString will lead to bad access

我有一個要求,使用 NSInvocation 的

  • (void)getArgument:(void *)argumentLocation atIndex:(NSInteger)idx;

得到論點。 參數主要是NSString,所以,在我的function中:

- (void)forwardInvocation:(NSInvocation *)invocation {
    [invocation retainArguments];
    NSString *biz;
   [invocation getArgument:&biz atIndex:2];
   NSString *statKey;
   [invocation getArgument:&statKey atIndex:3];
   getOriginalSelectorName:rawSelName blockArgCount:blockArgCount];
   allowed = [self allowPerformSensitiveSelector:rawSelector biz:[biz copy] statKey:[statKey copy]];
   ...
}

但是我遇到了雙重免費崩潰。 經過調試,我發現問題是,

因為調用實際上是持有一個__CFString object,它被分配在堆上,並且長度> = 10,例如'1234567890',所以當我調用[invocation getArgument:&statKey atIndex:3]; , statKey 用指向 1234567890 的指針寫入:

例如,

(lldb) p statKey  // set by `getArgument:&statKey`
(__NSCFString *) $0 = 0x00000002839492e0 @"1234567890"
(lldb) mem read 0x00000002839492e0
0x2839492e0: 01 e9 be d8 a1 21 00 00 8c 07 00 00 04 00 00 00  .....!..........
0x2839492f0: 0a 31 32 33 34 35 36 37 38 39 30 00 00 00 00 00  .1234567890.....
(lldb) p statKey // outer one, passed from method parameters, resided in invocation
(__NSCFString *) $1 = 0x000000028372f780 @"1234567890"
(lldb) mem read 0x000000028372f780
0x28372f780: 01 e9 be d8 a1 21 00 00 ad 07 00 00 04 00 00 00  .....!..........
0x28372f790: e0 fd 97 83 02 00 00 00 0a 00 00 00 00 00 00 00  ................

所以新的 NSString *statKey 實際上是一個指針。

當調用完成時,我會遇到崩潰,就像雙釋放一樣,因為它們都指向0x21a1d8bee901

如果字符串類似於[[NSMutableString alloc] initWithString:@'123456789'] ,即使這是一個 CFString,但在調用[invocation getArgument:&statKey atIndex:3]時,它將是

NSTaggedPointerString * @"123456789" 0x9c98d935e3d914c6.

所以我假設字符串的長度為 10 是邊界。

所以我想問,我該如何解決這個問題? 我試過 [statKey copy] 或 [invocation retainArguments];,不工作。 謝謝!

這很可能與NSInvocation 返回值非常相似,但由於 EXC_BAD_ACCESS 導致應用程序崩潰,但對於[invocation getArgument:...]而不是返回值。
發生的情況是NSInvocation方法不知道值適合指針優化的底層類型( NSTaggedPointerString * ),因此 ARC 試圖釋放它。

修復應該是:

NSString __unsafe_unretained *statKey;
[invocation getArgument:&statKey atIndex:3];

或者:

void *statKey;
[invocation getArgument:&statKey atIndex:3];

此處也描述了類似的問題: https://stackoverflow.com/a/56604328/5329717

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM