블록 인수를 NSInvocation
에 전달하려고 시도했지만 앱이 충돌합니다. 호출은 네트워크 요청을 작성하고 성공 또는 실패 블록을 호출합니다. 문제는 네트워크 요청이 완료되기 전에 블록 할당이 해제된다는 것입니다. 나는 Block_copy
hackery로 작동하도록 만들었지 만, Instruments를 사용하여 누수를보고하지 않습니다.블록 인수가있는 NSInvocation
질문 : - 정적 분석기 또는 계측기가보고하지 않아도 누출이있을 수 있습니까? - 블록을 "보유"하는 더 좋은 방법이 있습니까?
// Create the NSInvocation
NSMethodSignature *methodSignature = [target methodSignatureForSelector:selector];
NSInvocation* invoc = [NSInvocation invocationWithMethodSignature:methodSignature];
[invoc setTarget:target];
[invoc setSelector:selector];
// Create success and error blocks.
void (^successBlock)(id successResponse) = ^(id successResponse) {
// Some success code here ...
};
void (^errorBlock)(NSError *error) = ^(NSError *error) {
// Some failure code here ...
};
/*
Without the two Block_copy lines, the block gets dealloced too soon
and the app crashes with EXC_BAD_ACCESS
I tried [successBlock copy] and [failureBlock copy] instead,
but the app still crashes.
It seems like Block_copy is the only way to move the block to the heap in this case.
*/
Block_copy((__bridge void *)successBlock);
Block_copy((__bridge void *)errorBlock);
// Set the success and failure blocks.
[invoc setArgument:&successBlock atIndex:2];
[invoc setArgument:&errorBlock atIndex:3];
[invoc retainArguments]; // does not retain blocks
// Invoke the method.
[invoc invoke];
업데이트 : 아래 코드를 업데이트했습니다. 블록은 NSMallocBlocks
이지만 앱은 계속 충돌합니다. 다음과 같이
// Create success and error blocks.
int i = 0;
void (^successBlock)(id successResponse) = ^(id successResponse) {
NSLog(@"i = %i", i);
// Some success code here ...
};
void (^errorBlock)(NSError *error) = ^(NSError *error) {
NSLog(@"i = %i", i);
// Some failure code here ...
};
/*** Both blocks are NSMallocBlocks here ***/
// Set the success and failure blocks.
void (^successBlockCopy)(id successResponse) = [successBlock copy];
void (^errorBlockCopy)(NSError *error) = [errorBlock copy];
/*** Both blocks are still NSMallocBlocks here - I think copy is a NoOp ***/
// Set the success and failure blocks.
[invoc setArgument:&successBlockCopy atIndex:2];
[invoc setArgument:&errorBlockCopy atIndex:3];
[invoc retainArguments]; // does not retain blocks
// Invoke the method.
[invoc invoke];
블록은 체인에서 아래로 전달됩니다 결국 HTTP에 따라 성공 또는 실패 블록을 호출
methodN
methodN
→ method1
→
NSInvocation
→ NSProxy
(forwardInvocation:
NSInvocation
사용) 응답.
모든 단계에서 블록을 복사해야합니까? 위의 예는 첫 번째 NSInvocation
에 대한 이야기입니다. 적절한 단계마다 [invocation retainArguments];
이 필요합니까? ARC를 사용하고 있습니다.
시도해 보았습니다. successBlock = [successBlock cop 와이]; 및 errorBlock = [오류 블록 복사]; 하지만이 오류와 동일한 충돌이 발생합니다. 주소에 개체 파일의 섹션을 가리키는 섹션이 포함되어 있지 않습니다. . 앞에서 언급 한 것처럼 Block_copy 라인을 추가하면 충돌을 방지 할 수 있지만 메모리가 누설되는지는 확실하지 않습니다. – pshah
현재 사용중인'Block_copy'에는 문서화 된 효과가 없습니다. 보시다시피, 문제가되는'invoke '에 의해 정의되지 않은 결과는 다른 정의되지 않은 효과를 갖습니다. 진정한 해결책은 아닙니다. 그리고 좀비조차도 스택 객체를 인위적으로 유지할 수 없기 때문에 여기에서 디버그하는 것을 도와주지 않습니다. 스택이 다시 커지면 스택 객체를 덮어 씁니다. – Tommy
Block_copy를 호출하면 블록이 스택 대신 힙에 저장됩니다. 그리고, 나는 여전히 successBlock 대신에 [successBlock copy]를 호출에 전달하는 것이 왜 효과가 있는지 파악할 수 없다. – pshah