我有来自C ++编写的库的一些事件,它在后台线程中工作:
virtual void OnData(const char* data)
{
NSLog(@"Here 'data' string is present %s", data);
@autoreleasepool {
NSString* sData= [NSString stringWithCString:data encoding:NSUTF8StringEncoding];
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"Here _sometimes_ 'data'(%s) is nil (\0). But sData is always present %@", data, sData);
[callback OnData:sData];
});
};
}
有时我在参数变量的dispatch_async块中有NULL(我怀疑它实际上是垃圾)。但是本地NSString变量总是在这里。为什么呢?
P.S。在这种情况下,我真的必须使用@autoreleasepool
吗?
答案 0 :(得分:3)
在执行异步块时,您无法保证const char *data
指向的缓冲区的生命周期。 data
可能是指向该点的悬空指针(应该假设为这样)。在任何异步引用中或在最初创建的上下文之外使用C样式指针是非常危险的。
您应该使用内存管理对象(例如NSData
,NSString
等),或者,如果您坚持使用C样式指针并且需要在异步块中引用此指针,请复制将数据发送到您自己的缓冲区,使用该缓冲区,然后在异步例程中使用该缓冲区时释放它。在这种情况下,您拥有sData
,所以在此之后不要引用data
,你会没事的。
P.S。您稍后会问在这种情况下是否必须使用@autoreleasepool
。
简而言之,在大多数情况下,不需要额外的自动释放池。值得注意的是,当使用Grand Central Dispatch(例如dispatch_async
)时,它有自己的自动释放池,因此您不必创建一个。而且,当你的主线程再次回到它的运行循环时,它的池就会耗尽。简而言之,在实例化自己的NSThread
对象时,只需要手动创建自动释放池。
话虽如此,有时您会在返回运行循环之前执行大量内存密集型操作时引入自动释放池。在这种情况下,您将添加自动释放池,以减少应用程序的峰值内存使用量。但这似乎不是其中之一。
答案 1 :(得分:1)
如果你有这样的事情:
void CallOnData()
{
char *test = malloc(5 * sizeof(char));
strcpy(test, "test");
OnData(test);
free(test);
}
您应该期望数据为" NULL"在街区。
假设您使用的是ARC,则不需要自动释放。