【问题标题】:Getting a runtime exception获取运行时异常
【发布时间】:2011-05-27 13:41:19
【问题描述】:
-(BOOL)createTimer
{
    stRs232Timer*   pEvent = malloc(sizeof(stRs232Timer));

    pEvent->bPersistent = YES;                              // setup timer structure
    pEvent->wAppTimerId = 95;
    pEvent->uPeriod     = 50;
    pEvent->bStopped    = NO;
    pEvent->uExpirationTime = 10;

    NSLog(@"bPersistent:%d",pEvent->bPersistent);
    NSLog(@"wAppTimerId:%d",pEvent->wAppTimerId);
    NSLog(@"uPeriod:%d",pEvent->uPeriod);
    NSLog(@"bStopped:%d",pEvent->bStopped);


    NSData* myData = [NSData dataWithBytes:(stRs232Timer*)pEvent length:sizeof(stRs232Timer*)];

    wTimerId = 99;
    pEvent->uPeriod = 51;
    myData = [NSData dataWithBytes:(stRs232Timer*)pEvent length:sizeof(stRs232Timer*)];
         [m_cAppIdMap setObject:myData forKey:[NSNumber numberWithUnsignedShort:wTimerId]];
    wTimerId = 96;
    pEvent->uPeriod = 52;
    myData = [NSData dataWithBytes:(stRs232Timer*)pEvent length:sizeof(stRs232Timer*)];
    [m_cAppIdMap setObject:myData forKey:[NSNumber numberWithUnsignedShort:wTimerId]];
    wTimerId = 97;
    pEvent->uPeriod = 53;
    myData = [NSData dataWithBytes:(stRs232Timer*)pEvent length:sizeof(stRs232Timer*)];
    [m_cAppIdMap setObject:myData forKey:[NSNumber numberWithUnsignedShort:wTimerId]];
    wTimerId = 98;
    pEvent->uPeriod = 54;
    myData = [NSData dataWithBytes:(stRs232Timer*)pEvent length:sizeof(stRs232Timer*)];
    [m_cAppIdMap setObject:myData forKey:[NSNumber numberWithUnsignedShort:wTimerId]];
    wTimerId = 95;
    pEvent->uPeriod = 55;
    myData = [NSData dataWithBytes:(stRs232Timer*)pEvent length:sizeof(stRs232Timer*)];
    [m_cAppIdMap setObject:myData forKey:[NSNumber numberWithUnsignedShort:wTimerId]];

    NSLog(@"The dictionary count now is:%d",[m_cAppIdMap count]);
    NSLog(@"The dictionary values now is:");
    NSLog(@"%@",m_cAppIdMap);

    [m_cPendingEventList addObject:myData];
    NSLog(@"EventList:%@",m_cPendingEventList);

    [self ChangeTimer:95 withPeriod:10];

    free(pEvent);
    return YES;
}

-(BOOL)ChangeTimer:(unsigned short)wTimerIds withPeriod:(uint8_t)uPeriod
{
 stRs232Timer*   pEvent;
    NSLog(@"Into the changeTimer");
    pEvent = (stRs232Timer*)[m_cAppIdMap objectForKey:[NSNumber numberWithUnsignedShort:wTimerIds]];
    NSLog(@"The val is:%@",pEvent);
    if(pEvent!=nil){
        pEvent->bStopped = NO;
        pEvent->uPeriod = uPeriod;
        NSLog(@"completed");
        }       

    return YES;
}

main.m
----------
int main (int argc, const char * argv[]) {

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    NSArray1* arr = [[NSArray1 alloc]init];
    [arr createTimer];
    [pool drain];
    return 0;
}

我收到 EXC_BAD_ACCESs 运行时异常。为什么会这样。我没有访问任何已释放的内存。

已编辑:

2011-05-30 11:21:45.191 NSArray[1091:a0f] bPersistent:1
2011-05-30 11:21:45.194 NSArray[1091:a0f] wAppTimerId:95
2011-05-30 11:21:45.195 NSArray[1091:a0f] uPeriod:50
2011-05-30 11:21:45.195 NSArray[1091:a0f] bStopped:0
2011-05-30 11:21:45.196 NSArray[1091:a0f] *** __NSAutoreleaseNoPool(): Object 0x100110180 of class NSConcreteData autoreleased with no pool in place - just leaking
2011-05-30 11:21:45.196 NSArray[1091:a0f] *** __NSAutoreleaseNoPool(): Object 0x1001102f0 of class NSConcreteData autoreleased with no pool in place - just leaking
2011-05-30 11:21:45.197 NSArray[1091:a0f] *** __NSAutoreleaseNoPool(): Object 0x100110410 of class NSCFNumber autoreleased with no pool in place - just leaking
2011-05-30 11:21:45.197 NSArray[1091:a0f] *** __NSAutoreleaseNoPool(): Object 0x100110a70 of class NSConcreteData autoreleased with no pool in place - just leaking
2011-05-30 11:21:45.198 NSArray[1091:a0f] *** __NSAutoreleaseNoPool(): Object 0x100110ab0 of class NSCFNumber autoreleased with no pool in place - just leaking
2011-05-30 11:21:45.198 NSArray[1091:a0f] *** __NSAutoreleaseNoPool(): Object 0x100110ad0 of class NSConcreteData autoreleased with no pool in place - just leaking
2011-05-30 11:21:45.199 NSArray[1091:a0f] *** __NSAutoreleaseNoPool(): Object 0x100110b10 of class NSCFNumber autoreleased with no pool in place - just leaking
2011-05-30 11:21:45.199 NSArray[1091:a0f] *** __NSAutoreleaseNoPool(): Object 0x100110b30 of class NSConcreteData autoreleased with no pool in place - just leaking
2011-05-30 11:21:45.200 NSArray[1091:a0f] *** __NSAutoreleaseNoPool(): Object 0x100110b70 of class NSCFNumber autoreleased with no pool in place - just leaking
2011-05-30 11:21:45.201 NSArray[1091:a0f] *** __NSAutoreleaseNoPool(): Object 0x1001109e0 of class NSConcreteData autoreleased with no pool in place - just leaking
2011-05-30 11:21:45.201 NSArray[1091:a0f] *** __NSAutoreleaseNoPool(): Object 0x1001105d0 of class NSCFNumber autoreleased with no pool in place - just leaking
2011-05-30 11:21:45.202 NSArray[1091:a0f] The dictionary count now is:5
2011-05-30 11:21:45.202 NSArray[1091:a0f] The dictionary values now is:
2011-05-30 11:21:45.203 NSArray[1091:a0f] {
    98 = <5f000136 000a0000>;
    97 = <5f000135 000a0000>;
    96 = <5f000134 000a0000>;
    99 = <5f000133 000a0000>;
    95 = <5f000137 000a0000>;
}
2011-05-30 11:21:45.203 NSArray[1091:a0f] EventList:(
    <5f000137 000a0000>
)
2011-05-30 11:21:45.204 NSArray[1091:a0f] Into the changeTimer
2011-05-30 11:21:45.204 NSArray[1091:a0f] *** __NSAutoreleaseNoPool(): Object 0x100111130 of class NSCFNumber autoreleased with no pool in place - just leaking
2011-05-30 11:21:45.205 NSArray[1091:a0f] The val is:<5f000137 000a0000>
2011-05-30 11:21:45.205 NSArray[1091:a0f] completed

这是我在移除 NSAutoreleasePool 和 [pool drain] 后得到的输出。

如果我不删除这两个,我将 EXC_BAD_ACCESS 作为运行时异常。当我调试时,当涉及到 [pool drain] 时,我得到了异常(EXC_BAD_ACCESS);声明。

我不知道为什么会发生这种情况。

【问题讨论】:

  • 您是否尝试过设置断点并单步执行您的代码?你试过打开 NSZombies 吗?为什么 wTimerId 没有维度?
  • @Abizern:抱歉回复晚了。请看编辑
  • @Abizern:如何开启NSZombies?

标签: objective-c


【解决方案1】:

看看这一行(和类似的):

NSData* myData = [NSData dataWithBytes:(stRs232Timer*)pEvent length:sizeof(stRs232Timer*)];

字节数等于指向 stRs232Timer 数据的指针的大小,例如 32 位系统为 4 字节,64 位系统为 8 字节 - 但不是 stRs232Timer 结构的大小。所以你复制的字节不够。

演员表也不是必须的,所以应该是这样的:

NSData* myData = [NSData dataWithBytes: pEvent length: sizeof(stRs232Timer)];

顺便说一句,第一个实例在保存到字典之前将被覆盖。

稍后

ChangeTimer 中你应该使用NSData bytes 方法而不是直接转换为stRs232Timer

pEvent = (stRs232Timer*)[[m_cAppIdMap objectForKey:[NSNumber numberWithUnsignedShort:wTimerIds]] bytes];

这会给你指向数据的指针,将 NSData 直接转换为stRs232Timer 是错误的。

【讨论】:

  • @Tomasz:感谢您指出这一点。我现在了解我在代码中所做的危险事情。但我仍然收到 EXC_BAD_ACCESS 运行时异常。我不知道我在做什么错误的事情。
  • 到底是在什么地方崩溃的?
  • 第一:您是否更改了代码以将适当数量的字节复制到 NSData?该代码仍然复制指针大小缓冲区。您还应该删除第一个 NSData dataWithBytes 调用,因为它只是浪费 CPU,正如我所说的,它几乎立即被覆盖。现在我找到了另一个,但在 ChangeTimer 中,查看更新的答案:将 NSData 转换为 stRs232Timer*:它们是不同的动物,您应该改为转换 NSData 字节。正如有人建议的那样:在 EXC_BAD_ACCESS 使用 NSZombie 运行 Instruments 的情况下,它帮助我几次找出过度释放的对象。
  • 关于 Instruments:恐怕这里解释的太复杂了,简单来说:如果你启动 Instruments 你应该能够选择 Zombies,然后在 Instruments 运行中它会继续并在发现僵尸时显示一个小弹出窗口,在那里您可以显示导致访问过度释放对象的堆栈跟踪。
  • 但是僵尸只对过度释放的对象有帮助,如果你的指针出错了,它不会。所以现在可能不是解决方案。你已经注册了苹果开发者连接吗?如果是,我强烈建议您在苹果开发者网站上查找他们的播客。他们有关于使用 Instruments for Zombies、调试内存问题等的精彩视频。它极大地帮助了我理解如何使用它。注册后完全免费,您只需使用iTunes下载即可。
猜你喜欢
  • 1970-01-01
  • 2017-07-01
  • 2012-04-28
  • 2012-08-07
  • 2019-02-22
  • 1970-01-01
  • 1970-01-01
  • 2018-08-20
  • 2013-09-20
相关资源
最近更新 更多