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

Unitialized read and unaddressable access errors

我在 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 returns 是一个值而不是指针。我也不想使用 C 类型转换,因为它在非洲杀死 children(你知道,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

First of, what are the vao, vbo and ibo variables? They are integers; actually indices in OpenGL that points to some data in the VRAM (I'm no expert). They are guaranteed to be initialized and are only destroyed in this destructor. The proof is that my application works perfectly fine. Is there a way to fix this drmemory's warning or get rid of it?

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

至于您的实际问题,您正在为 class 调用析构函数两次。我不知道为什么您显示的少量代码会发生这种情况,但它解释了为什么获取 vbo 的地址会产生无效的堆地址。

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

The general rule is, if you can't guarantee that the OpenGL RAII object will be destroyed while the context is still around, then don't wrap OpenGL objects inside RAII C++ classes. glDeleteBuffers() crashes during destructor call

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