【问题标题】:"Access violation reading location" while accessing a global vector访问全局向量时的“访问冲突读取位置”
【发布时间】:2009-10-15 12:40:22
【问题描述】:

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

我现在正在为我的游戏编写一个简单的 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);
}

main.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。

(代码已更新)

【问题讨论】:

  • irrw::driver->getTexture(szFileName) 是否有可能生成 AV 而不是 push_back? “读取位置 0x00000558”看起来可能是在追逐一个 NULL 指针; irrw::driver 初始化了吗?
  • 是的。我编辑了我的帖子并添加了一些额外的代码行以显示 irrw::driver 已经初始化。你说的这个“AV”是怎么回事?
  • 这有什么更新吗?真正的原因是什么?

标签: c++ irrlicht


【解决方案1】:

调用堆栈指向执行大量工作的行。我建议查看以下检查列表以追查问题:

  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,因此您只在发布版本中注意到了这一点。只是一个疯狂的想法。

【讨论】:

  • 我编辑并改进了我的帖子。请考虑改进您的答案:)。
【解决方案2】:

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

驱动程序得到了无效的对象。矢量没问题。

【讨论】:

    【解决方案3】:

    我的猜测是 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);
    }
    

    【讨论】:

    • 我试过了,代码停在“ITexture *foo”行。我现在该怎么办?
    【解决方案4】:

    正如 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);
    

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

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

    【讨论】:

    • 我尝试了您的代码,但 assert() 通过了,程序停止,调用堆栈指向同一行(push_back)。这是否意味着 irrw::driver 已正确初始化?
    • REV:当我尝试拆分 push_back 和 getTexture 时,程序停在 getTexture 行,并且“自动”选项卡中的“path_to_szFileName”变量的值(调试时的左下屏幕)变成红色(是的,文本颜色)。
    • 我已经好几年没真正用过MSVC了,所以不知道RED是什么意思。我认为这可能只是意味着它最近发生了变化。如果 getTexture 触发了访问冲突,那么您可能需要在 Irrlicht 的文档或源代码中进行一些挖掘以找出原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-31
    • 2016-05-28
    • 2017-01-09
    • 2014-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多