0

-- 首先,我不知道如果我在命名空间下声明它,而不是在类或函数中声明它是否可以称为“全局向量”。--

我现在正在为我的游戏编写一个简单的 Irrlicht ( http://irrlicht.sourceforge.net ) 包装器,以使事情变得更简单和容易,但最近在尝试 push_back 时出现“访问冲突读取位置”错误声明在全局范围。

到目前为止,这是我的代码:

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);
}

主.cpp:

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

和错误:

Game.exe 中 0x692804d6 处未处理的异常:0xC0000005:访问冲突读取位置 0x00000558。

现在我真的不知道如何解决这个问题。

任何形式的帮助将不胜感激:)

以下是一些原型:

    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;

仅供参考,我使用的是 MSVC++ 2008 EE。

(代码更新)

4

4 回答 4

3

调用堆栈指向一个做很多事情的行。我建议仔细检查以下检查列表以追查问题:

  1. irrw::driver 是否指向正确的对象,或者它可能是一个空/未初始化的指针?
  2. irrw::driver->getTexture(..) 采用什么类型的参数?它真的是一个 irr::core::stringc 还是其他东西(也许是一个普通的 C 字符串?)。
  3. 'szFileName' 的值是多少;你能打印它(即用 printf 或类似的东西)吗?也许它已经损坏了,因为 irr:core::stringc 类做了一些有趣的事情。
  4. irrw::driver->getTexture(..) 的返回类型是什么 - 它真的返回 irr::video::ITexture* 还是可能返回其他东西(某种指针包装器)?
  5. irrw::driver->getTexture(szFileName); 的返回值是多少?称呼?质地合适吗?

更新:现在您的问题已更新,这是一个可能发生的新想法:

您的代码的简化版本是这样的:

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();

如果 iGraphicsDriver 具有未经检查的值,则可能是 drvT 保持未初始化。在这种情况下,createDevice() 调用可能会返回一个无效设备,进而在调用 getVideoDriver() 时返回一个无效的视频驱动程序。

我建议您将 drvT 初始化为合理的值,例如:

E_DRIVER_TYPE drvT = EDT_SOFTWARE;

这样可以避免这个问题。

FWIW,这个错误在过去可能没有被注意到,因为 EDT_SOFTWARE 可能是 0 的 #define。在调试版本中,“drvT”可能会自动初始化为 0,所以你只在发布版本中注意到了这一点。只是一个疯狂的想法。

于 2009-10-15T12:54:33.150 回答
0

irrw::driver = irrw::device->getVideoDriver();

驱动程序得到了无效的对象。矢量是好的。

于 2009-10-15T13:14:13.887 回答
0

正如 Frerich Raabe 所说,您在一行代码中执行了多项操作,并且极有可能是push_back调用以外的其他内容产生了访问冲突。如果有帮助,您可以拆分语句以查看发生访问冲突的时间点。

io::path path_to_szFileName = szFileName;
assert(irrw::driver != NULL);
irr::video::ITexture* texture = irrw::driver->getTexture(path_to_szFileName);
irrw::TextureCollector.push_back(texture);

像这样拆分表达式应该可以让您确定问题出在哪里。

编辑:修复了我的代码的问题。

于 2009-10-15T13:34:23.077 回答
0

我的猜测是 getTexture 失败了。

您确定 szFileName 将其定向到磁盘上实际存在的文件吗?尝试对完全限定路径进行硬编码,以查看当前工作目录是否存在问题。

像这样重写代码,使用调试器单步执行并检查所有值。确保 foo 实际上指向某个有效的地方,并确保由于向量而实际发生访问冲突。

void irrLoadImage(irr::core::stringc szFileName, int iID, int iTextureFlag)
{
        //........
        ITexture *foo = irrw::driver->getTexture(szFileName);
        irrw::TextureCollector.push_back(foo);
        irrw::TextureConnector.push_back(iID);
}
于 2009-10-15T13:57:52.360 回答