Vì vậy, tôi đang sử dụng các khối đệ quy. Tôi hiểu rằng đối với một khối được đệ quy nó cần phải được bắt đầu bằng từ khóa __block, và nó phải được sao chép để nó có thể được đặt trên heap. Tuy nhiên, khi tôi làm điều này, nó được hiển thị như là một rò rỉ trong dụng cụ. Có ai biết tại sao hay làm thế nào tôi có thể vượt qua nó?Các khối đệ quy trong rò rỉ mục tiêu-C trong ARC
Vui lòng lưu ý trong mã bên dưới tôi đã tham chiếu đến nhiều khối khác, nhưng không có mục nào trong số đó là đệ quy.
__block NSDecimalNumber *(^ProcessElementStack)(LinkedList *, NSString *) = [^NSDecimalNumber *(LinkedList *cformula, NSString *function){
LinkedList *list = [[LinkedList alloc] init];
NSDictionary *dict;
FormulaType type;
while (cformula.count > 0) {
dict = cformula.pop;
type = [[dict objectForKey:@"type"] intValue];
if (type == formulaOperandOpenParen || type == formulaListOperand || type == formulaOpenParen) [list add:ProcessElementStack(cformula, [dict objectForKey:@"name"])];
else if (type == formulaField || type == formulaConstant) [list add:NumberForDict(dict)];
else if (type == formulaOperand) [list add:[dict objectForKey:@"name"]];
else if (type == formulaCloseParen) {
if (function){
if ([function isEqualToString:@"AVG("]) return Average(list);
if ([function isEqualToString:@"MIN("]) return Minimum(list);
if ([function isEqualToString:@"MAX("]) return Maximum(list);
if ([function isEqualToString:@"SQRT("]) return SquareRoot(list);
if ([function isEqualToString:@"ABS("]) return EvaluateStack(list).absoluteValue;
return EvaluateStack(list);
} else break;
}
}
return EvaluateStack(list);
} copy];
NSDecimalNumber *number = ProcessElementStack([formula copy], nil);
CẬP NHẬT Vì vậy, trong nghiên cứu của riêng tôi, tôi đã phát hiện ra rằng vấn đề dường như không phải làm gì với các tham chiếu đến các khối khác khối này sử dụng. Nếu tôi làm điều gì đó đơn giản như thế này, nó không bị rò rỉ:
__block void (^LeakingBlock)(int) = [^(int i){
i++;
if (i < 100) LeakingBlock(i);
} copy];
LeakingBlock(1);
Tuy nhiên, nếu tôi thêm một khối khác trong này, nó bị rò rỉ:
void (^Log)(int) = ^(int i){
NSLog(@"log sub %i", i);
};
__block void (^LeakingBlock)(int) = [^(int i){
Log(i);
i++;
if (i < 100) LeakingBlock(i);
} copy];
LeakingBlock(1);
Tôi đã thử bằng cách sử dụng __block từ khóa cho Log() và cũng đã thử sao chép nó, nhưng nó vẫn bị rò rỉ. Bất kỳ ý tưởng?
CẬP NHẬT 2 Tôi đã tìm ra cách ngăn chặn sự rò rỉ, nhưng hơi khó chịu. Nếu tôi chuyển đổi thông qua trong khối để một id yếu, và sau đó đúc id yếu trở lại vào một loại khối, tôi có thể ngăn chặn rò rỉ.
void (^Log)(int) = ^(int i){
NSLog(@"log sub %i", i);
};
__weak id WeakLogID = Log;
__block void (^LeakingBlock)(int) = [^(int i){
void (^WeakLog)(int) = WeakLogID;
WeakLog(i);
if (i < 100) LeakingBlock(++i);
} copy];
LeakingBlock(1);
Chắc chắn có cách nào tốt hơn?
Cảm ơn bạn đã chia sẻ nghiên cứu của mình, tôi chưa từng nghe nói về việc phải sao chép khối. Tuy nhiên, có vẻ như một LLVM gần đây phát ra một cảnh báo tại cuộc gọi đệ quy "nắm bắt LeakingBlock" mạnh mẽ trong khối này có khả năng dẫn đến một chu kỳ giữ lại ".Cách duy nhất tôi tìm thấy để xoa dịu trình biên dịch là sử dụng một ptr yếu riêng biệt cho khối hơi tương tự như câu trả lời của bạn dưới đây, mặc dù nó khó sử dụng mà tôi bị cám dỗ để ghi đè cục bộ cảnh báo thay thế. Tôi muốn được quan tâm đến việc xem xét của bạn một khi bạn thử trình biên dịch mới nhất. –
@smallduck Ban đầu, tôi đã sử dụng 'copy' vì nó khiến khối được sao chép sang đống từ ngăn xếp. Trong một thời gian mà làm việc tốt và tôi cũng đã nhận lỗi trình biên dịch "đệ quy". Tôi đã xóa 'copy' khỏi mã của tôi (như được phản ánh trong câu trả lời của tôi) và nó đã hoạt động (trong khi trước đó tôi nhận được' EXC_BAD_ACCESS'. Tôi đoán rằng Apple đã thay đổi từ khóa '__block' để tạo các khối trên heap thay vì ngăn xếp ... nhưng đó chỉ là phỏng đoán –
@smallduck Thật ra, tôi đã từ bỏ việc sử dụng các khối để đệ quy. Có, nó có thể được thực hiện nhưng hơi khó sử dụng và có quá nhiều cạm bẫy. giữ lại các chu kỳ (có thể rất tệ khi đệ quy) và nó trở nên khó đọc Vì vậy, thông thường tôi chỉ cần gắn các phương thức/chức năng để thực hiện đệ quy –