如何解决奇怪的KERN_INVALID_ADDRESS例外?
我正面临着一个奇怪的OC异常,看来我正在向已发布的地址发送消息,但是当我
例外
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x0000000000000010
VM Region Info: 0x10 is not in any region. Bytes before following region: 4304617456
REGION TYPE START - END [ VSIZE] PRT/MAX SHRMOD REGION DETAIL
UNUSED SPACE AT START
--->
__TEXT 100934000-100a98000 [ 1424K] r-x/r-x SM=COW ...x/APP
Termination Signal: Segmentation fault: 11
Termination Reason: Namespace SIGNAL,Code 0xb
Terminating Process: exc handler [18302]
Triggered by Thread: 22
下面的代码不严格,仅显示逻辑(代码在一个串行调度队列中运行)
struct st_type {
void *arg;
};
static NSMutableDictionary *dictionary;
// init values
void init ()
{
// there is a static dictionary to retain the object
dictionary = [[NSMutableDictionary alloc]init];
// an object reference saved in dictionary and a struct holds it's pointer
NSObject *obj = [[NSObject alloc]init];
struct st_type *st = malloc(sizeof(struct st_type));
st->arg = (__bridge void *)obj;
dictionary[@"cached"] = obj;
// then the struct * passes to every where,I think it's safe because the object always in the dictionary.
...
}
// the only place to release the nsobject,so I think there is no chance to EXC_BAD_ACCESS,but ...
void release_object(struct st_type *st,NSObject obj){
[dictionary removeObjectForKey:@"cached"];
st->arg = NULL;
}
// some where to use the struct
void use_struct(struct st_type *st){
if(st->arg == NULL){
return;
}
// if I add try catch,it never crashs
// @try {
NSObject *obj = (__bridge NSObject*)st->arg;
[obj description]; // crash here.
// } @catch (NSException *exception) { print some log but it never reaches here... }
}
解决方法
如果我正确理解,您想将对Objective-C对象的引用存储为void *
。例如,这与旧的context
或userInfo
指针作为回调传递给工作表的用例类似。
有关示例,请参见ARC: __bridge versus __bridge_retained using contextInfo test case。我还假定您正在使用ARC(请阅读Casting and Object Lifetime Semantics)。
假设该结构的生存期比Objective-C对象的生存期更长,并且您在该结构中显式设置和释放了该对象,则不需要字典来进行内存管理。
一旦分配了结构和对象(分别使用malloc
和[[XX alloc] init]
),就可以将对象的所有权移出ARC并使用{{1 }}投。
要使用该对象,请使用st->arg
进行投射。这不会更改所有权。
准备释放对象时,请使用(__bridge_retained void *)
进行投射,将所有权传回ARC。然后,您可以将(__bridge NSObject *)
指针设置为(__bridge_transfer NSObject *)
。
总的来说,像这样:
void *
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。