统一读取和不可修复的访问错误

Unitialized read and unaddressable access errors

本文关键字:访问 错误 可修复 读取      更新时间:2023-10-16

我在Windows7下执行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

首先,vao、vbo和ibo变量是什么?它们是整数;实际上是OpenGL中的索引,指向VRAM中的一些数据(我不是专家)。它们保证被初始化,并且只在此析构函数中被销毁。证明我的应用程序运行良好。有没有办法修复或消除这个drmemory的警告?

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

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

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

一般规则是,如果不能保证OpenGL RAII对象在上下文仍然存在时会被破坏,那么不要将OpenGL对象包装在RAII C++类中。glDeleteBuffers()在析构函数调用期间崩溃

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