NSOperationQueue批量添加500次操作时参数为空问题求助
问题分析与解决办法
这问题我之前排查过类似的,核心坑点在于你对cStringUsingEncoding:返回的char*生命周期理解有误,导致异步执行时指针失效。
为什么循环次数到500就出问题?
你在循环里创建的parm1是局部NSString对象,ARC会在每次循环结束后自动释放它。而[parm1 cStringUsingEncoding:NSUTF8StringEncoding]返回的char*,本质是指向NSString内部临时缓冲区的指针——这个指针只在NSString对象存活期间有效。
当循环次数少的时候,被释放的NSString内存还没被系统复用,char可能还能读到旧值;但循环到500次时,内存被频繁复用,之前的缓冲区已经被清空或覆盖,队列执行block时,这个char就变成了空值或垃圾内存。
另外你调用代码里还有个笔误:[string cStringUsingEncoding:...]应该是[parm1 cStringUsingEncoding:...],不过这不是核心问题。
最优解决方案:改用NSString传递,在block内转char*
直接把NSString对象传给someMethod,让block捕获这个对象——ARC会自动帮你管理它的生命周期,确保block执行时对象还存活,此时再转换char*就安全了。
修改后的someMethod:
- (void)someMethod:(NSString *)param1 { NSBlockOperation *theOp = [NSBlockOperation blockOperationWithBlock: ^{ // 仅在需要使用时才转换为char*,此时param1被block持有,生命周期安全 const char *cParam = [param1 cStringUsingEncoding:NSUTF8StringEncoding]; // 在这里使用cParam执行你的操作 }]; [[MyQueueService sharedMyQueueService].operationQueue addOperation:theOp]; }
调用代码也简化了:
for (int index = 1; index < 500; index++) { MyClass *classInstance = [[MyClass alloc] init]; NSString *parm1 = [NSString stringWithFormat:@"%d", index]; [classInstance someMethod:parm1]; }
备选方案:手动复制char*到堆内存(不推荐,容易内存泄漏)
如果因为某些原因必须传递char*,可以用strdup把字符串复制到堆内存,然后在block执行完毕后手动释放:
- (void)someMethod:(char *)param1 { // 复制到堆内存 char *copiedParam = strdup(param1); NSBlockOperation *theOp = [NSBlockOperation blockOperationWithBlock: ^{ // 使用copiedParam执行操作 // ... // 用完记得释放 free(copiedParam); }]; [[MyQueueService sharedMyQueueService].operationQueue addOperation:theOp]; }
这种方式需要自己管理内存,容易遗漏释放导致泄漏,所以优先推荐第一种方案。
内容的提问来源于stack exchange,提问作者Gyanendra
相关产品推荐
相关产品推荐

