调用非虚拟成员函数时访问冲突

时间:2011-12-24 18:15:34

标签: c++ access-violation

我有一些代码运行了很多次,并突然报告访问冲突。

for(std::list<Projectile>::iterator it = projectiles.begin(); it != projectiles.end();) {
    bool finished = ...

    // try to print address of collides(), prints always 1
    std::cout << &Projectile::collides << std::endl; 
    // here it crashes:
    if(it->collides(&hero)) { 
        std::cout << "Projectile hits " << hero.getName() << std::endl;
        finished = it->apply(&hero);
    }

    // ...
    if(finished) {
        it = projectiles.erase(it);
    } else {
        ++it;
    }
}

因此,VS调试堆栈跟踪表示在行if(it->collides(&hero)) {中,程序尝试调用cdcdcdcd()处的方法,这会导致访问冲突。

根据VS,

it*ithero是有效对象。

所以我假设cdcdcdcd()实际应该是collides()。由于collides是一种非虚方法,它的地址基本上不应该改变或者?

问题是方法collides()在成功之前执行了好几次,但突然间它不再起作用了。

地址是否可以更改?我覆盖了吗?

请帮帮我!此外,我感谢有关此代码不正常的任何信息:)

2 个答案:

答案 0 :(得分:2)

0xcdcdcdcd是Win32 Debug CRT Heap使用的填充模式;假设您在Windows上运行调试器,这可能是一个重要的线索。有一个不错的explanation of the heap fill patterns here

我的猜测是你在某种程度上要么在其他地方使迭代器无效,要么有其他缓冲区溢出或悬空指针或其他问题。

Application Verifier可能有助于诊断这一点。您可能还想查看问题How to debug heap corruption errors?中提到的其他内容或Any reason to overload global new and delete?中的一些技巧(免责声明:目前我对两者都有最高评价的答案)。

如果您的STL库具有调试功能,它也可能有助于解决这个问题。 Metrowerks(现在飞思卡尔)Codewarrior有定义_MSL_DEBUG,例如,它可用于构建标准库的版本(包括std::list),它将检测迭代器失效等常见问题(在某些运行时)成本)。

如果您使用的话,Visual Studio的debug iterator support可能符合要求。

答案 1 :(得分:0)

你的终止条件似乎错了 [编辑:实际上它看起来是正确的,即使它仍然让我害怕。见评论。] 。当finished变为真时,你擦除当前的射弹,然后将迭代器设置为......某事。没有理由认为循环将在此时终止。 it最终可能会开始指向列表之外,或者指向其他无效对象(调试器不会始终标记为此对象)。

当您擦除射弹时,您应该使用“break”明确地离开循环。