未初始化的读取和不可寻址的访问错误

时间:2015-03-21 18:45:21

标签: c++ opengl memory memory-management

我在Windows 7下执行drmemory来检查我的内存泄漏并发现了一些对我来说很奇怪的东西:

Error #1: UNINITIALIZED READ: reading 0x08842fdc-0x08842fe0 4 byte(s)
# 0 ig7icd32.dll!DllMain                             +0x56017  (0x5a995ec7 <ig7icd32.dll+0xd5ec7>)
# 1 ig7icd32.dll!DllMain                             +0x54bad  (0x5a994a5e <ig7icd32.dll+0xd4a5e>)
# 2 AbstractVertexData::vertexAttribPtr               [D:/CodeBlocks Workspace/Tests/BasicScene_Tests/BasicScene_InitialTest/Engine/Graphics/AbstractVertexData.cpp:36]
# 3 DrawBuffers::buildBuffers                         [D:/CodeBlocks Workspace/Tests/BasicScene_Tests/BasicScene_InitialTest/Engine/Graphics/DrawBuffers.cpp:49]
# 4 DrawBuffers::DrawBuffers                          [D:/CodeBlocks Workspace/Tests/BasicScene_Tests/BasicScene_InitialTest/Engine/Graphics/DrawBuffers.cpp:14]
# 5 Core::Load                                        [D:/CodeBlocks Workspace/Tests/BasicScene_Tests/BasicScene_InitialTest/Engine/Core/Load.cpp:178]
# 6 main                                              [D:/CodeBlocks Workspace/Tests/BasicScene_Tests/BasicScene_InitialTest/main.cpp:10]

此错误指向此代码,更准确地指向最后一行:

glVertexAttribPointer(layout,
                      getShaderAttribs()[layout]->nbComponents,
                      static_cast<GLenum>(getShaderAttribs()[layout]->attribDataType),
                      getShaderAttribs()[layout]->shouldNormalize,
                      getVertexStride(layout),
                      reinterpret_cast<const void*>(getVertexAttribStart(layout)));

OpenGL从最后一个参数想要的是一个const GLvoid *(const void *)。它在语义上是一个int,表示属性数组的偏移量。无论如何,这条线路工作得非常好,但我想摆脱这个警告。我不能使用引用,因为函数getVertexAttribStart返回一个值而不是一个指针。我也不想使用C型铸造,​​因为它杀死了非洲的儿童(你知道,C是魔鬼)。

还有这个警告:

Error #4: UNADDRESSABLE ACCESS beyond heap bounds: reading 0x0863fcc4-0x0863fcc8 4 byte(s)
# 0 ig7icd32.dll!DllMain                   +0x52721  (0x5a9925d1 <ig7icd32.dll+0xd25d1>)
# 1 ig7icd32.dll!DllMain                   +0x52660  (0x5a992511 <ig7icd32.dll+0xd2511>)
# 2 ig7icd32.dll!DllMain                   +0x516e7  (0x5a991598 <ig7icd32.dll+0xd1598>)
# 3 DrawBuffers::~DrawBuffers               [D:/CodeBlocks Workspace/Tests/BasicScene_Tests/BasicScene_InitialTest/Engine/Graphics/DrawBuffers.cpp:23]
# 4 DrawBuffers::~DrawBuffers               [D:/CodeBlocks Workspace/Tests/BasicScene_Tests/BasicScene_InitialTest/Engine/Graphics/DrawBuffers.cpp:26]
# 5 Core::Unload                            [D:/CodeBlocks Workspace/Tests/BasicScene_Tests/BasicScene_InitialTest/Engine/Core/Unload.cpp:6]
# 6 main                                    [D:/CodeBlocks Workspace/Tests/BasicScene_Tests/BasicScene_InitialTest/main.cpp:23]

此警告的代码:

DrawBuffers::~DrawBuffers()
{
    glDeleteBuffers(1, &ibo);
    glDeleteBuffers(1, &vbo); // I'm the line 23!!!
    glDeleteVertexArrays(1, &vao);
    delete vertexData;
}

首先,vao,vbo和ibo变量是什么?他们是整数;实际上OpenGL中的索引指向VRAM中的一些数据(我不是专家)。它们保证被初始化,并且只在这个析构函数中被销毁。证明是我的应用程序完美无缺。有没有办法解决这个drmemory的警告或摆脱它?

这是我的引擎的概念(你需要draw.io):https://drive.google.com/file/d/0B5dq0OS4n55JcHJqcTBmZHJWYjg/view?usp=sharing

2 个答案:

答案 0 :(得分:4)

  

首先,vao,vbo和ibo变量是什么?他们是整数;实际上OpenGL中的索引指向VRAM中的一些数据(我不是专家)。它们保证被初始化,并且只在这个析构函数中被销毁。证明是我的应用程序完美无缺。有没有办法解决这个drmemory的警告或摆脱它?

虽然与您的问题无关,但在OpenGL中知道vaovboibo 保留名称可能会有所帮助。它们在技术上不必与任何数据相关联(它们在调用glGenBuffers (...)glGenArrays (...)之后立即以此状态存在,但在绑定它们之前)。在像C ++这样的语言中没有简单的模拟,因为如果你在C ++中new某个对象,它将立即调用构造函数 - GL推迟构造对象,直到名字被第一次绑定。

至于你的实际问题,你要两次为你的类调用析构函数。我不知道为什么会出现这样的小代码,但它解释了为什么使用vbo的地址会产生无效的堆地址。

答案 1 :(得分:0)

花了我一些时间,但我忘记了一些非常重要的事情:

  

一般规则是,如果你不能保证在上下文仍然存在的情况下销毁OpenGL RAII对象,那么就不要在RAII C ++类中包装OpenGL对象。   glDeleteBuffers() crashes during destructor call

在我的主循环中,我在卸载数据之前关闭了窗口,即上下文。