当前位置: 首页 > 知识库问答 >
问题:

多次调用glGetTexImage时出现缓冲区溢出错误

邴修远
2023-03-14

我正在创建一个类来使用OpenGL管理图像。要加载图像,我使用SOIL加载PNG。因为我需要检查碰撞,所以我想得到透明像素。所以我尝试使用:glGetTexImage获取数据

构造函数加载图像:

Image::Image(string imagePath, unsigned int flags){
    this->imagePath=imagePath;
    this->pxData=NULL;
    texture=SOIL_load_OGL_texture
    (
     imagePath.c_str(),
     SOIL_LOAD_AUTO,
     SOIL_CREATE_NEW_ID,
     flags
    );

    //Use that to subdivide in sprites the texture
    glGetTexLevelParameteriv(GL_TEXTURE_2D, texture, GL_TEXTURE_WIDTH, &textureWidth);
    glGetTexLevelParameteriv(GL_TEXTURE_2D, texture, GL_TEXTURE_HEIGHT, &textureHeight);
    glBindTexture(GL_TEXTURE_2D, this->texture);
    //cout << "Real Dimensions - " << textureWidth << "-" << textureHeight;

    loadPixels(); //multiple instances of image generates error here
}

LoadPixels在我的结构中加载像素数据。

typedef struct PixelData{
    unsigned char r;
    unsigned char g;
    unsigned char b;
    unsigned char a;
} PixelData;
PixelData* pxData;

然后在loadPixels中存储数据:

void Image::loadPixels(){
    pxData = new PixelData[textureHeight*textureWidth];
    glGetTexImage(GL_TEXTURE_2D, 1, GL_RGBA, GL_UNSIGNED_BYTE , pxData);
}

问题是,如果我创建一个图像:

Image img("/Developer/img.png", SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT);

它很好用。

如果我创建了很多图像:

    Image img("/Developer/img.png", SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT);
    Image img2("/Developer/img2.png", SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT);
    Image img3("/Developer/img3.png", SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT);
    Image img4("/Developer/img4.png", SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT);
    Image img5("/Developer/img5.png", SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT);
    Image img6("/Developer/img6.png", SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT);
    Image img7("/Developer/img7.png", SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT);
    Image img8("/Developer/img8.png", SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT);
    Image img9("/Developer/img9.png", SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT);
    Image img10("/Developer/img10.png", SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT);

然后我的程序崩溃了:

错误是:

OpenGL Game Engine(35463,0x7fff7b121310) malloc: *** error for object 0x104017808: incorrect checksum for freed object - object was probably modified after being freed.
*** set a breakpoint in malloc_error_break to debug

如果我对glGetTexImage(GL_纹理_2D,1,GL_RGBA,GL_无符号_字节,pxData)进行注释;它运行良好,所以我认为问题不在于分配。

我只需要获取像素数据来存储它,我想用这些像素创建一些数据,所以我需要获取纹理的像素。

注:

程序在imagePath停止。c_str()和sigabort如果我取消对loadPixels的注释,如果我对其进行注释,它将加载所有纹理

多亏了奥黛丽,我得到了更多的信息。

glGetTexLevelParameteriv(GL_TEXTURE_2D, this->texture, GL_TEXTURE_WIDTH, &textureWidth);
glGetTexLevelParameteriv(GL_TEXTURE_2D, this->texture, GL_TEXTURE_HEIGHT, &textureHeight);

Real Dimensions - 128-128
Real Dimensions - 64-64
Real Dimensions - 32-32
Real Dimensions - 16-16

这是相同的图像,但尺寸越来越小。

我检查了id,它每次都会创建一个新的id,那么为什么大小会变得混乱呢?

有没有其他方法来获取该数据,我这里缺少什么?另一个问题,这种方法获取绑定纹理,有没有一种方法可以使用纹理id获取纹理数据?

共有2个答案

韩玉石
2023-03-14
glGetTexLevelParameteriv(GL_TEXTURE_2D, texture, GL_TEXTURE_HEIGHT, &textureHeight);

第二个参数不接受纹理ID。它是一个mipmap级别。首先需要绑定纹理,然后在放置纹理的位置使用0调用此函数。

具体来说,你的纹理ID几乎肯定会被实例化为“0”、“1”、“2”等。。。每次使用一个连续的值调用glGetTexLevelParameteriv时,您都要求在当前绑定的纹理上使用较小的mipmap级别。你的第一次通话没有失败,这让我怀疑,SOIL\u load\u OGL\u texture实际上没有在它返回之前解除绑定。

请记住,几乎没有OpenGL函数将纹理、缓冲区或着色器ID作为参数,而是作用于当前绑定的对象。通常与实际ID一起使用的唯一函数是创建、销毁或绑定对象的函数,例如glGenTexturesglDeleteTexturesglBindTexture

逑禄
2023-03-14

根据评论中的讨论,似乎getGlTexImage正在溢出pxData缓冲区。如果您发布函数的输出给您的textureWidthtextureHeight是什么,我们可能就能找出问题所在。(例如,您确定getter函数的返回类型与变量textureWidth等之间的兼容性吗?)

编辑:我会检查你的

尝试重新排序并重写以下内容:

glBindTexture(GL_TEXTURE_2D, this->texture);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &textureWidth);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &textureHeight);

 类似资料:
  • 缓冲区溢出的漏洞随着冯·诺依曼 1 构架的出 现就已经开始出现了。 在1988年随着莫里斯互联网蠕虫的广泛传播他们开始声名狼藉。不幸的是, 同样的这种攻击一直持续到今天。 到目前为止,大部分的缓冲区溢出的攻击都是基于摧毁栈的方式。 大部分现代计算机系统使用栈来给进程传递参数并且存储局部变量。 栈是一种在进程映象内存的高地址内的后进先出(LIFO)的缓冲区。 当程序调用一个函数时一个新的“栈帧”会被

  • 当程序试图在临时数据存储区域(缓冲区)中存储比预期要容纳的更多数据时,会出现缓冲区溢出。由于创建缓冲区以包含有限数量的数据,因此额外信息可能溢出到相邻缓冲区中,从而破坏其中保存的有效数据。 示例 这是缓冲区溢出的经典示例。它演示了一个简单的缓冲区溢出,它是由第一个依赖外部数据来控制其行为的场景引起的。无法限制用户输入的数据量,程序的行为取决于用户放入的字符数。 动手实践 第1步 - 我们需要使用姓

  • 首先,我要声明,我打的这篇文档,原稿是《黑手缓冲区溢出教程》,而不是作者出的正版书,在这里向王炜老大道歉!!因为我兜里的那个实在是那什么,外加上我们烟台这里买不到…

  • GSAIOException:错误代码:393238缓冲区溢出,没有可用空间 但我不知道这意味着什么。谁能解释一下是哪种例外。我可以在哪里搜索代码找到问题?

  • 前言 进程的内存映像 常用寄存器初识 call,ret 指令的作用分析 什么是系统调用 什么是 ELF 文件 程序执行基本过程 Linux 下程序的内存映像 栈在内存中的组织 缓冲区溢出 实例分析:字符串复制 缓冲区溢出后果 缓冲区溢出应对策略 如何保护 ebp 不被修改 如何保护 eip 不被修改? 缓冲区溢出检测 缓冲区注入实例 准备:把 C 语言函数转换为字符串序列 注入:在 C 语言中执行

  • Summary To find out more about buffer overflow vulnerabilities, please go to Buffer Overflow pages. See the OWASP article on Buffer Overflow Attacks. See the OWASP article on Buffer Overflow Vulnerabi