glTexImage2D 读取超出缓冲区范围 (iOS)
glTexImage2D reads beyond bounds of buffer (iOS)
在下面的简单代码中,我将 1 通道数据加载到纹理中。我将 glTexImage2D()
与 GL_LUMINANCE
(一种单通道格式)和 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 才不会溢出(2 比预期大小 4 大)。
1x1 和 4x4 的尺寸似乎没有这个问题,但是 2x2 和 3x3 有。好像有点武断。
怎么了?
感谢@genpfault 的评论,我已经解决了。
我需要将解包对齐设置为 1:
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
具体来说,解包对齐方式决定了每行开头的对齐方式。默认值为4。由于我的行没有任何特殊的对齐方式,并且行字节之间没有间隙,因此对齐方式应为1。
第一行将始终对齐,因为 malloc
分配了 16 位对齐的缓冲区。但是第二行和后续行与默认对齐方式 4 不对齐,除非行长度是 4 的倍数(这解释了为什么 2x2 和 3x3 不起作用,但 4x4 起作用)。 1x1 正好可以工作,因为它没有第二行。
在下面的简单代码中,我将 1 通道数据加载到纹理中。我将 glTexImage2D()
与 GL_LUMINANCE
(一种单通道格式)和 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 才不会溢出(2 比预期大小 4 大)。
1x1 和 4x4 的尺寸似乎没有这个问题,但是 2x2 和 3x3 有。好像有点武断。
怎么了?
感谢@genpfault 的评论,我已经解决了。
我需要将解包对齐设置为 1:
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
具体来说,解包对齐方式决定了每行开头的对齐方式。默认值为4。由于我的行没有任何特殊的对齐方式,并且行字节之间没有间隙,因此对齐方式应为1。
第一行将始终对齐,因为 malloc
分配了 16 位对齐的缓冲区。但是第二行和后续行与默认对齐方式 4 不对齐,除非行长度是 4 的倍数(这解释了为什么 2x2 和 3x3 不起作用,但 4x4 起作用)。 1x1 正好可以工作,因为它没有第二行。