Ios SIGSEGV调试:cocos2d iphone中定义的update()方法在哪里?
我正试图解决Ios SIGSEGV调试:cocos2d iphone中定义的update()方法在哪里?,ios,objective-c,cocos2d-iphone,Ios,Objective C,Cocos2d Iphone,我正试图解决cocos2diphone1.0.1中的SIGSEGV信号错误。我必须指出,尽管我努力了几个小时,但实际上我无法复制这次崩溃。我只知道这是因为测试人员 我收集了尽可能多的信息。首先,这里是TestFlight回溯: 太好了。让我们看看 CCScheduler 代码>蜱虫>代码>方法。它相当大,因此我这里只有发生错误的代码块(在问题的底部,您可以看到完整的方法): 好。所以我们找到了罪犯的线索 让我们看看,impMethod是类型TICK\u IMP,定义为 typedef void
cocos2diphone1.0.1
中的SIGSEGV
信号错误。我必须指出,尽管我努力了几个小时,但实际上我无法复制这次崩溃。我只知道这是因为测试人员
我收集了尽可能多的信息。首先,这里是TestFlight回溯:
太好了。让我们看看<代码> CCScheduler <代码>代码>蜱虫>代码>方法。它相当大,因此我这里只有发生错误的代码块(在问题的底部,您可以看到完整的方法):
好。所以我们找到了罪犯的线索
让我们看看,impMethod
是类型TICK\u IMP
,定义为
typedef void (*TICK_IMP)(id, SEL, ccTime);
嗯。impMethod(elt->currentTimer,updateSelector,dt)
本身没有任何问题
仔细看,我最好的猜测是elt->currentTimer
可能有问题
起初,我认为如果elt
是NULL
指针,调用elt->currentTimer
可能会导致分段错误。然而,我最近被告知,即使elt
为NULL
,向它发送消息也不会导致SIGSEGV
错误
我已经确认了这一点,因为我最终用if(elt!=NULL)
包装了该方法,但它仍然存在,所以问题一定是其他原因
在没有线索的情况下,我突然想到,这段代码并不能导致错误。它一定是我代码中其他地方的模糊信息
让我看看。如果我在罪魁祸首行之前执行NSLog
,如下所示:
NSLog(@"[%@ %@]" , [elt->target class],NSStringFromSelector(updateSelector));
我可以告诉什么是最后一个被更新的预定对象,甚至可以得到相应的方法
在使我的测试人员再次崩溃后,我最终得到了以下结果:
[游戏更新]
好极了<代码>游戏是游戏的主要场景,因此问题似乎与此类场景有关
但是等等。对于我的场景,没有这样的方法update
。我从来没有实现过这样的事情
然后我想既然Game
是CCScene
对象,也许CCScene
确实有这样的方法。但我看到了它的实现,却没有。但是等等,CCScene
是CCNode
的子类!让我们来看看<代码> CCNode <代码> .<
。。。CCNode
中也没有update
方法
我确实发现了一些关于CCNode
的奇怪之处:
-(void) scheduleUpdate;
显然,它负责安排每帧调用一次update
方法,而且确实如此。下面是这类程序的一个特定行:
[target methodForSelector:updateSelector];
其中目标
应该是游戏
,更新选择器
是@selector(更新:)
但是,这没有任何意义:在哪里应该实现这个更新
方法?我在CCNode
的任何地方都找不到它。因此,它怎么可能安排这种方法呢
通常,我会说这就是导致错误的原因——我们正在安排一个未实现的方法,从而导致SIGSEGV
错误。然而,这很奇怪,因为如果这是真的,那么它应该一直崩溃,但事实并非如此
这就是我试着调试这个错误所得到的结果。我错过了什么
我知道你不能告诉我问题出在哪里,但我相信我得到了一条重要的线索,你可以解释一下:在cocos2d中update
在哪里实现
这是
CCScheduler
中勾选
方法的完整代码,以防万一:
-(void) tick: (ccTime) dt {
updateHashLocked = YES;
if( timeScale_ != 1.0f )
dt *= timeScale_;
// Iterate all over the Updates selectors
tListEntry *entry, *tmp;
// updates with priority < 0
DL_FOREACH_SAFE( updatesNeg, entry, tmp ) {
if( ! entry->paused && !entry->markedForDeletion )
entry->impMethod( entry->target, updateSelector, dt );
}
// updates with priority == 0
DL_FOREACH_SAFE( updates0, entry, tmp ) {
if( ! entry->paused && !entry->markedForDeletion )
{
entry->impMethod( entry->target, updateSelector, dt );
}
}
// updates with priority > 0
DL_FOREACH_SAFE( updatesPos, entry, tmp ) {
if( ! entry->paused && !entry->markedForDeletion )
entry->impMethod( entry->target, updateSelector, dt );
}
// Iterate all over the custome selectors
for(tHashSelectorEntry *elt=hashForSelectors; elt != NULL; ) {
currentTarget = elt;
currentTargetSalvaged = NO;
if( ! currentTarget->paused ) {
// The 'timers' ccArray may change while inside this loop.
for( elt->timerIndex = 0; elt->timerIndex < elt->timers->num; elt->timerIndex++) {
elt->currentTimer = elt->timers->arr[elt->timerIndex];
elt->currentTimerSalvaged = NO;
impMethod( elt->currentTimer, updateSelector, dt);
if( elt->currentTimerSalvaged ) {
// The currentTimer told the remove itself. To prevent the timer from
// accidentally deallocating itself before finishing its step, we retained
// it. Now that step is done, it's safe to release it.
[elt->currentTimer release];
}
elt->currentTimer = nil;
}
}
if (elt != NULL) {
// elt, at this moment, is still valid
// so it is safe to ask this here (issue #490)
elt = elt->hh.next;
// only delete currentTarget if no actions were scheduled during the cycle (issue #481)
if( currentTargetSalvaged && currentTarget->timers->num == 0 )
[self removeHashElement:currentTarget];
}
}
// delete all updates that are morked for deletion
// updates with priority < 0
DL_FOREACH_SAFE( updatesNeg, entry, tmp ) {
if(entry->markedForDeletion )
{
[self removeUpdateFromHash:entry];
}
}
// updates with priority == 0
DL_FOREACH_SAFE( updates0, entry, tmp ) {
if(entry->markedForDeletion )
{
[self removeUpdateFromHash:entry];
}
}
// updates with priority > 0
DL_FOREACH_SAFE( updatesPos, entry, tmp ) {
if(entry->markedForDeletion )
{
[self removeUpdateFromHash:entry];
}
}
updateHashLocked = NO;
currentTarget = nil;
}
-(无效)勾选:(ccTime)dt{
updatehashlock=YES;
如果(时间刻度=1.0f)
dt*=时间刻度;
//迭代所有更新选择器
tListEntry*条目,*tmp;
//优先级<0的更新
DL_FOREACH_SAFE(updatesNeg、entry、tmp){
如果(!entry->paused&!entry->markedForDeletion)
条目->导入方法(条目->目标,更新选择器,dt);
}
//优先级==0的更新
DL_FOREACH_SAFE(更新0、条目、tmp){
如果(!entry->paused&!entry->markedForDeletion)
{
条目->导入方法(条目->目标,更新选择器,dt);
}
}
//优先级>0的更新
DL_FOREACH_SAFE(更新操作系统、条目、tmp){
如果(!entry->paused&!entry->markedForDeletion)
条目->导入方法(条目->目标,更新选择器,dt);
}
//迭代所有自定义选择器
for(tHashSelectorEntry*elt=hashForSelectors;elt!=NULL;){
当前目标=elt;
currentTargetSalvaged=否;
如果(!currentTarget->暂停){
//“定时器”阵列在此循环内可能会发生变化。
对于(elt->timerIndex=0;elt->timerIndextimers->num;elt->timerIndex++){
elt->currentTimer=elt->timers->arr[elt->timerIndex];
elt->CurrentTimerSalvage=否;
impMethod(elt->currentTimer,updateSelector,dt);
如果(elt->CurrentTimerSalvated){
//currentTimer通知移除本身。以防止计时器
//在完成步骤之前意外地释放了自己,我们保留了
//现在,这一步已经完成,可以安全地释放它了。
[elt->currentTimer release];
}
elt->currentTimer=nil;
}
}
如果(elt!=NULL){
//目前,英语教学仍然有效
//因此,在这里问这个问题是安全的(第490期)
elt=elt->hh.next;
//仅在循环期间未计划任何操作时删除currentTarget(问题#481)
我
[target methodForSelector:updateSelector];
-(void) tick: (ccTime) dt {
updateHashLocked = YES;
if( timeScale_ != 1.0f )
dt *= timeScale_;
// Iterate all over the Updates selectors
tListEntry *entry, *tmp;
// updates with priority < 0
DL_FOREACH_SAFE( updatesNeg, entry, tmp ) {
if( ! entry->paused && !entry->markedForDeletion )
entry->impMethod( entry->target, updateSelector, dt );
}
// updates with priority == 0
DL_FOREACH_SAFE( updates0, entry, tmp ) {
if( ! entry->paused && !entry->markedForDeletion )
{
entry->impMethod( entry->target, updateSelector, dt );
}
}
// updates with priority > 0
DL_FOREACH_SAFE( updatesPos, entry, tmp ) {
if( ! entry->paused && !entry->markedForDeletion )
entry->impMethod( entry->target, updateSelector, dt );
}
// Iterate all over the custome selectors
for(tHashSelectorEntry *elt=hashForSelectors; elt != NULL; ) {
currentTarget = elt;
currentTargetSalvaged = NO;
if( ! currentTarget->paused ) {
// The 'timers' ccArray may change while inside this loop.
for( elt->timerIndex = 0; elt->timerIndex < elt->timers->num; elt->timerIndex++) {
elt->currentTimer = elt->timers->arr[elt->timerIndex];
elt->currentTimerSalvaged = NO;
impMethod( elt->currentTimer, updateSelector, dt);
if( elt->currentTimerSalvaged ) {
// The currentTimer told the remove itself. To prevent the timer from
// accidentally deallocating itself before finishing its step, we retained
// it. Now that step is done, it's safe to release it.
[elt->currentTimer release];
}
elt->currentTimer = nil;
}
}
if (elt != NULL) {
// elt, at this moment, is still valid
// so it is safe to ask this here (issue #490)
elt = elt->hh.next;
// only delete currentTarget if no actions were scheduled during the cycle (issue #481)
if( currentTargetSalvaged && currentTarget->timers->num == 0 )
[self removeHashElement:currentTarget];
}
}
// delete all updates that are morked for deletion
// updates with priority < 0
DL_FOREACH_SAFE( updatesNeg, entry, tmp ) {
if(entry->markedForDeletion )
{
[self removeUpdateFromHash:entry];
}
}
// updates with priority == 0
DL_FOREACH_SAFE( updates0, entry, tmp ) {
if(entry->markedForDeletion )
{
[self removeUpdateFromHash:entry];
}
}
// updates with priority > 0
DL_FOREACH_SAFE( updatesPos, entry, tmp ) {
if(entry->markedForDeletion )
{
[self removeUpdateFromHash:entry];
}
}
updateHashLocked = NO;
currentTarget = nil;
}