在下面的简单代码中,我将1通道数据加载到纹理。我将glTexImage2D()
与GL_LUMINANCE
(1通道格式)和GL_UNSIGNED_BYTE
一起使用,因此每像素需要一个字节。我分配一个大小等于像素数(2 x 2)的缓冲区,它代表输入像素数据(对于我们的目的,像素的值无关紧要。)
在启用Address Sanitizer的情况下运行以下代码时,它会在调用glTexImage2D()
时检测到堆缓冲区溢出,并说它尝试读取超出堆分配缓冲区的范围:
#import <OpenGLES/ES2/gl.h>
//...
EAGLContext* context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
[EAGLContext setCurrentContext:context];
GLsizei width = 2, height = 2;
void *data = malloc(width * height); // contents don't matter for now
glTexImage2D(GL_TEXTURE_2D,
0,
GL_LUMINANCE,
width,
height,
0,
GL_LUMINANCE,
GL_UNSIGNED_BYTE,
data);
这是100%可重现的,并且在iOS模拟器和设备上都会发生。只有将缓冲区的大小增加到6才会溢出(比预期的4大小大2)。
1x1和4x4的尺寸似乎没有这个问题,但是2x2和3x3都有。这似乎有点武断。
有什么问题?
答案 0 :(得分:0)
由于@ genpfault的评论,我已经解决了这个问题。
我需要将解包对齐设置为1:
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
具体来说,解包对齐确定每行开始的对齐方式。默认值为4.由于我的行没有任何特殊对齐,并且行字节之间没有间隙,因此对齐应为1.
第一行将始终对齐,因为malloc
分配16对齐的缓冲区。但是第二行和后续行未对齐,默认对齐为4,除非行长度是4的倍数(这解释了为什么2x2和3x3不起作用,但4x4不起作用)。 1x1碰巧工作,因为它没有第二行。