Sha*_*ley 1 c++ pointers segmentation-fault stdlist
我有一个指针列表,它们引用了需要转向我游戏的时间对象.此示例TimeObject*
在列表中有两个.此代码有效,直到从列表中删除某个项目:当发生这种情况时,另一个项目指向无效的地址.TimeObject
发生这种情况时都不会被删除; 只有指针从列表中删除.是什么造成的?
TimeUnlink()
被称为TimeObject::Tick()
.它不是静态的,但列表是.
我在Linux上使用GCC 4.6.2.该程序没有线程.
void TimeObject::TimeUnlink()
{
printf("Time unlink\n");
TimeObject::list_.remove(this);
timeobject_flags_.linked_ = 0;
}
void GameTime::GameTurn(uint16_t _time)
{
tick_ += _time;
for(std::list<TimeObject*>::iterator it = TimeObject::list_.begin(); it != TimeObject::list_.end(); ++it)
{
TimeObject *timeobject = *it;
printf("GameTurn %p\n", timeobject);
if(timeobject == NULL) { printf("continue\n"); continue; }
timeobject->time_ += _time;
if(timeobject->speed_ && timeobject->time_ >= timeobject->speed_)
{
while(timeobject->timeobject_flags_.linked_ && timeobject->time_ - timeobject->speed_ > 0)
{
timeobject->time_ -= timeobject->speed_;
if(timeobject->mapobject_)
{
timeobject->mapobject_->Tick();
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
错误输出:
GameTurn 0xc1e048
GameTurn 0x696828
GameTurn 0xc1e048
GameTurn 0x696828
GameTurn 0xc1e048
GameTurn 0x696828
GameTurn 0xc1e048
Time unlink
GameTurn (nil)
continue
GameTurn 0xc1e030
Program received signal SIGSEGV, Segmentation fault.
0x00000000004059a1 in GameTime::GameTurn(unsigned short) ()
Run Code Online (Sandbox Code Playgroud)
小智 5
在输出序列中,指针在0xc1e048
和之间交替0x696828
,这意味着它0xc1e048
是列表中的第一项,0x696828
是第二项.基于此,看起来对象at 在循环中间0xc1e048
时GameTurn::GameTurn
被取消链接,很可能是在调用中timeobject->mapobject_->Tick()
,或者由@hmjd提到的另一个线程.从列表中删除对象会使指向该对象的迭代器无效.
假设代码是单线程的,并且调用Tick
导致问题,那么这样的事情可能会起作用:
void GameTime::GameTurn(uint16_t _time)
{
tick_ += _time;
for(std::list<TimeObject*>::iterator it = TimeObject::list_.begin(); it != TimeObject::list_.end(); )
{
TimeObject *timeobject = *it;
++it;
printf("GameTurn %p\n", timeobject);
if(timeobject == NULL) { printf("continue\n"); continue; }
timeobject->time_ += _time;
if(timeobject->speed_ && timeobject->time_ >= timeobject->speed_)
{
while(timeobject->timeobject_flags_.linked_ && timeobject->time_ - timeobject->speed_ > 0)
{
timeobject->time_ -= timeobject->speed_;
if(timeobject->mapobject_)
{
timeobject->mapobject_->Tick();
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
(唯一的区别是在增量it
从移动for
分配后声明循环体it
来timeobject
.推进it
,才能无效应该解决这个问题.
如果您的代码是多线程的,则需要一个互斥锁.