C++ – “Access violation reading location” while accessing a global vector

cirrlicht

— First of all, I don't know whether the vector can be called as a "global vector" if I declared it under a namespace, but not in a class or function. —

I'm now writing a simple Irrlicht (http://irrlicht.sourceforge.net) wrapper for my game to make things simpler and easier, but recently I got an "Access violation reading location" error when trying to push_back a vector declared in the global scope.

Here is my code so far:

irrwrap.cpp:

namespace irrw
{
    //.........
    IrrlichtDevice *device;
    IVideoDriver *driver;
    irr::core::array<irr::video::ITexture*> TextureCollector;
    vector<int> TextureConnector;
    //.........
}

//..............

void irrInit(int iGraphicsDriver, int iWindowWidth, int iWindowHeight, int iScreenDepth, bool bFullScreen)
{
    E_DRIVER_TYPE drvT;
    if(iGraphicsDriver == GD_SOFTWARE)
        drvT = EDT_SOFTWARE;
    else if(iGraphicsDriver == GD_D3D8)
        drvT = EDT_DIRECT3D8;
    else if(iGraphicsDriver == GD_D3D9)
        drvT = EDT_DIRECT3D9;
    else if(iGraphicsDriver == GD_OPENGL)
        drvT = EDT_OPENGL;

    //..............

    irrw::device = createDevice(drvT, dimension2d<u32>(iWindowWidth, iWindowHeight), iScreenDepth, bFullScreen);
    irrw::driver = irrw::device->getVideoDriver();
    //..................
}

void irrLoadImage(irr::core::stringc szFileName, int iID, int iTextureFlag)
{
    //........
    irrw::TextureCollector.push_back(irrw::driver->getTexture(szFileName)); // the call stack pointed to this line
    irrw::TextureConnector.push_back(iID);
}

main.cpp:

//.........
INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT)
{
    //.........
    irrInit(GD_OPENGL, 800, 600, 16, false);
    irrLoadImage("picture.jpg", 100, 1);
    //.........
}

and the error:

Unhandled exception at 0x692804d6 in Game.exe: 0xC0000005: Access violation reading location 0x00000558.

Now I really got no idea on how to fix the problem.

Any kind of help would be appreciated 🙂

Here are some prototypes:

    virtual ITexture* getTexture(const io::path& filename) = 0;
    typedef core::string<fschar_t> path; // under 'io' namespace
    typedef char fschar_t;
    typedef string<c8> stringc;
    typedef char c8;

Just FYI, I am using MSVC++ 2008 EE.

(CODE UPDATED)

Best Answer

The call stack points to a line which does a lot of stuff. I suggest going over the following check list to trace down the problem:

  1. Does irrw::driver point to a proper object, or is it maybe a null/uninitialized pointer?
  2. What type of argument does irrw::driver->getTexture(..) take? Is it really a irr::core::stringc or something else (maybe a plain C string?).
  3. What is the value of 'szFileName'; can you print it (i.e. with printf or the like)? Maybe it's corrupted since the irr:core::stringc class did something funny.
  4. What is the return type of irrw::driver->getTexture(..) - does it really return a irr::video::ITexture* or does it maybe return something else (some kind of pointer wrapper)?
  5. What is the return value of the irrw::driver->getTexture(szFileName); call? Is it a proper texture?

UPDATE: Now that your question was updated, here's a new idea what might be happening:

A simplified version of your code is this:

E_DRIVER_TYPE drvT;
if(iGraphicsDriver == foo) // iGraphicsDriver is an int
        drvT = abc;
else if(iGraphicsDriver == bar)
        drvT = xyz;
// ... and so on ...

irrw::device = createDevice(drvT, ... );
irrw::driver = irrw::device->getVideoDriver();

It might be that drvT stays uninitialized in case iGraphicsDriver has an unchecked value. In that case, the createDevice() call might return an invalid device, which in turn returns an invalid video driver when calling getVideoDriver().

I suggest that you initialize drvT to something reasonably, like:

E_DRIVER_TYPE drvT = EDT_SOFTWARE;

This would avoid the problem.

FWIW, this bug might've gone unnoticed in the past since EDT_SOFTWARE might be a #define for 0. In debug builds, 'drvT' might automatically be initialized to 0, so you only noticed this in a release build. Just a crazy idea.

Related Topic