多次调用glGetTexImage时发生缓冲区溢出错误
Buffer overflow error when calling glGetTexImage multiple times
我正在创建一个类来使用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_TEXTURE_2D,1,GL_RGBA,GL_UNSIGNED_BYTE,pxData);它运行良好,所以我想问题不在于分配。
我只需要得到像素数据来存储它,我想用这些像素创建一些数据,所以我需要得到纹理的像素。
注:
如果我取消对loadPixels的注释,程序将在带有sigabort的imagePath.c_str()处停止,如果我对其进行注释,它将加载所有纹理
多亏了Audrey,我得到了更多的信息。
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获取纹理数据?
根据评论中的讨论,getGlTexImage
似乎溢出了pxData
缓冲区。如果你发布给你textureWidth
和textureHeight
的函数的输出是什么,我们可能会找出问题所在。(例如,您确定getter函数的返回类型与变量textureWidth
等之间的兼容性吗?)
编辑:我会检查你的<Gl.h>
,看看函数glGetTexLevelParametersiv
的签名。我在网上看了一下,微软WINAPI版本的签名与OpenGL.org上的签名不同,两者都不同意你使用的签名。
尝试重新排序并重写为:
glBindTexture(GL_TEXTURE_2D, this->texture);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &textureWidth);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &textureHeight);
glGetTexLevelParameteriv(GL_TEXTURE_2D, texture, GL_TEXTURE_HEIGHT, &textureHeight);
第二个参数不采用纹理ID。它是一个mipmap级别。您需要首先绑定纹理,然后在放置纹理的位置使用0调用此函数。
具体来说,你的纹理ID几乎肯定会被实例化为"0"、"1"、"2"等。每次你用连续值调用glGetTexLevelParameteriv
时,你都会要求在当前绑定的纹理上有一个较小的mipmap级别。您的第一个调用没有失败,这让我怀疑SOIL_load_OGL_texture
实际上并没有在返回之前解除绑定。
请记住,几乎没有OpenGL函数将纹理、缓冲区或着色器ID作为参数,而是作用于当前绑定的对象。通常与实际ID一起使用的唯一函数是创建、销毁或绑定对象的函数,例如glGenTextures
、glDeleteTextures
和glBindTexture
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- 为什么我在leetcode上收到AddressSanitizer:地址0x602000000058上的堆缓冲区溢出错误
- 在 leetcode 上提交解决方案时出现堆栈缓冲区溢出错误
- 使用 strcat 获取缓冲区溢出错误
- LeetCode 1:两和 - 地址清理器:堆缓冲区溢出地址
- 使用向量的缓冲区溢出
- 重新增长阵列时出错:写入时缓冲区溢出
- Leetcode 1366:堆缓冲区溢出
- 缓冲区溢出 - 数组索引越界(严重)
- C++二维矢量导致缓冲区溢出
- 缓冲区溢出怎么会成为黑客的攻击
- 如何防止缓冲区溢出
- 应该如何读取堆缓冲区溢出错误消息?
- 自动截断和 null 终止缓冲区溢出中的字符串缓冲区
- 如果用户输入两个或多个由空格分隔的字符串C++如何防止缓冲区溢出?
- 我正在尝试使用回溯来解决 N queen 问题,但在编译时它会给出运行时错误(动态堆栈缓冲区溢出)
- 为什么 LeetCode 给出错误:地址清理器:堆缓冲区溢出
- 为什么错误 C6386 缓冲区溢出与 strsafe.h 字符串 Cch 函数
- 读取文件时字符缓冲区溢出
- C 文本写入随机数据.是否有缓冲区溢出