gpt4 book ai didi

ios - NSBlockOperation EXC_BAD_ACCESS

转载 作者:行者123 更新时间:2023-11-29 12:22:41 25 4
gpt4 key购买 nike

我创建了一个实现一些方法的类。这些方法由另一个类调用,并通过 NSBlockOperation 进行管理。

我的 NSBlockOperation 工作正常,我在尝试计算变量时遇到问题:

EXC_BAD_ACCESS

我在互联网上做了很多研究,this是最接近我的问题的一个。我试着像 sugerito 那样做,但你遇到了同样的问题。

你有什么建议吗?

编辑:

这是堆栈跟踪:

2015-05-09 15:24:45.976 OutParameters[12326:743087] Stack trace : (
0 OutParameters 0x000000010e5d6602 -[ListOperation _method1:] + 194
1 OutParameters 0x000000010e5d646f __25-[ListOperation method1:]_block_invoke + 95
2 Foundation 0x000000010e74257f __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 7
3 Foundation 0x000000010e6830b2 -[NSBlockOperation main] + 98
4 Foundation 0x000000010e665774 -[__NSOperationInternal _start:] + 645
5 Foundation 0x000000010e665383 __NSOQSchedule_f + 184
6 libdispatch.dylib 0x00000001113f4614 _dispatch_client_callout + 8
7 libdispatch.dylib 0x00000001113db6a7 _dispatch_queue_drain + 2176
8 libdispatch.dylib 0x00000001113dacc0 _dispatch_queue_invoke + 235
9 libdispatch.dylib 0x00000001113de3b9 _dispatch_root_queue_drain + 1359
10 libdispatch.dylib 0x00000001113dfb17 _dispatch_worker_thread3 + 111
11 libsystem_pthread.dylib 0x0000000111761637 _pthread_wqthread + 729
12 libsystem_pthread.dylib 0x000000011175f40d start_wqthread + 13
)

修改后的代码:

- (IBAction)testCallMethod:(id)sender {
NSString * output;
[self.listOperationObj method1:&output];
NSLog(@"Output: %@", output);
}

@interface ListOperation : NSObject

-(void)method1:(NSString**)output;

@end

#define MAX_OPERATIONS 10
//define a log-level
static int logLevel = CSLOG_LEVEL_INFO;
@interface ListOperation ()
// Tail used to synchronize the methods
@property NSOperationQueue *queue;
@end

#pragma mark - Public methods

@implementation ListOperation

- (id)init {
self = [super init];
if(self) {
_queue = [NSOperationQueue new];
if(_queue) {
[_queue setMaxConcurrentOperationCount:1];
}else {
NSLog(@"TokenMgr creation failed: error creating operation queue");
self = nil;
}
}
return self;
}

-(void)method1:(NSString *__autoreleasing *)output{
LOGFSTART
if([self _isQueueFull] == FALSE) {
WEAK
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
STRONG
[strongSelf _method1:output];
}];
[self.queue addOperation:operation];
[operation waitUntilFinished];
}
else {
LOGE(@"TokenMgr's queue is full, aborting operation");
}
LOGFEND
}

#pragma mark - private methods

-(void)_method1:(NSString *__autoreleasing *)output{
std::string testString = "try put string";
*output = [NSString stringWithUTF8String:testString.c_str()];
}

- (BOOL) _isQueueFull {
return self.queue.operationCount > MAX_OPERATIONS;
}

@end

如果我反复按下按钮,这个更改会给我同样的错误。

最佳答案

眼前的问题与方 block 无关。你有一个代码片段说:

- (IBAction)testCallMethod:(id)sender {
NSString *__autoreleasing * output;
[self.listOperationObj method1:output];
NSLog(@"Output: %@", *output);
}

那是行不通的,因为 output 不会指向有效的内存地址,当您尝试使用 *output = ... 取消引用未初始化的指针时,它会崩溃。

相反,那应该是:

- (IBAction)testCallMethod:(id)sender {
NSString *output;
[self.listOperationObj method1:&output];
NSLog(@"Output: %@", output);
}

现在 output 引用了一个真正的 NSString * 指针,您可以用对对象的引用来填充它。


还有第二个更深层次的问题,即对操作中实例化的对象使用 * __autoreleasing * 引用。操作有自己的自动释放池,因此在 testCallMethod 中使用对象时会出现竞争条件。

相反,人们通常使用完成 block 将数据传回给调用者。因此:

- (IBAction)testCallMethod:(id)sender {
[self.listOperationObj method2:^(NSString *output) {
NSLog(@"Output: %@", output);
}];
}

- (void)method2:(void (^)(NSString *))completionHandler {
LOGFSTART
if([self _isQueueFull] == FALSE) {
WEAK
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
STRONG
[strongSelf _method2:completionHandler];
}];
[self.queue addOperation:operation];
// [operation waitUntilFinished]; // not needed any more
}
else {
LOGE(@"TokenMgr's queue is full, aborting operation");
}
LOGFEND
}

-(void)_method2:(void (^)(NSString *))completionHandler {
std::string testString = "try put string";
NSString *output = [NSString stringWithUTF8String:testString.c_str()];
completionHandler(output);
}

请注意,顺便说一下,这也解决了您的示例的另一个问题,即您必须在其中放置一个 waitUntilFinished 调用。您永远不应从主线程调用 waitUntilFinished。如果您像上面那样使用完成 block ,则不再需要。

关于ios - NSBlockOperation EXC_BAD_ACCESS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30140318/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com