简体   繁体   中英

Access violation in call to non-virtual member function

I have some piece of code that runs many times and suddenly reports an 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;
    }
}

So VS debug stacktrace says that in line if(it->collides(&hero)) { the program tries to call a method at cdcdcdcd() which causes the access violation.

it , *it and hero are valid objects according to VS.

So I assume that cdcdcdcd() should actually be collides() . Since collides is a non-virtual method its address should basically not change or?

The thing is that the method collides() is executed several times before successfully, but suddenly it does not work anymore.

Can it be that the address is changed? Have I overwritten it?

Please help me! Also I appreciate information on anything that is not fine with this code :)

0xcdcdcdcd is a fill pattern used by the Win32 Debug CRT Heap; assuming you're running in a debugger on Windows, this may be a significant clue. There's a decent explanation of the heap fill patterns here .

My guess is you're somehow either invalidating the iterator elsewhere, or have some other buffer overflow or dangling pointer or other issue.

Application Verifier may help with diagnosing this. You may also want to look into the other things mentioned in the question How to debug heap corruption errors? or some of the techniques from Any reason to overload global new and delete? (disclaimer: at the moment I have the top-rated answer on both).

If your STL library has a debugging feature it may help ferret this out as well. Metrowerks (now Freescale) Codewarrior has the define _MSL_DEBUG , for example, that can be used to build a version of the standard libraries (including std::list ) which will detect common issues like iterator invalidation (at some runtime cost).

It looks like Visual Studio has debug iterator support which might fit the bill, if you're using that.

Your termination condition seems wrong [EDIT: actually it looks correct, even if it still scares me. See comments.] . When finished becomes true, you erase the current projectile and then set the iterator to ... something. There is no reason to think that the loop will terminate at this point. It's is likely that it will eventually either start pointing outside of the list, or to an otherwise invalid object (which your debugger will not always flag as such).

When you erase the projectile, you should just explicitly leave the loop using "break".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM