我有一些使用OpenGL 1.1的旧代码,它神秘地出现了段错误。我可能出错的一个地方是我在将数组提供给glNormalPointer
后free()
数组。这是允许的,还是OpenGL需要该指针上的内存才能保留?我一直假设数据是复制的。
double vertices[] = { ... };
double *normals = (double *)malloc(sizeof(vertices));
CalcNormals(vertices, normals, num_vertices); // Calculate the normal vectors.
GLuint my_display_list = glGenLists(1);
glNewList(my_display_list, GL_COMPILE);
glVertexPointer(3, GL_DOUBLE, 0, vertices);
glNormalPointer(GL_DOUBLE, 0, normals);
glDrawArrays(GL_TRIANGLES, 0, num_vertices);
glEndList();
free(normals); // Is this permitted?
// ...
glCallList(winglist);
编辑1:我注意到一些参考资料说glNormalPointer 和其他"客户端状态命令"不能包含在显示列表中。我想在这种情况下,在glNewList
和glEndList
之间包含glVertexPointer
和glNormalPointer
可能不会造成伤害,但我不妨将它们向上移动,在glNewList
之前发生。真正记录在显示列表中的是对glDrawArrays
的调用,对吧?
编辑 2:我尝试调用memset(normals, 0, sizeof(vertices))
在释放之前强制清除法线缓冲区,以使释放后使用的情况更加明显。由于场景绘制仍然正确,因此我得出结论,我分配的法线缓冲区在调用glDrawArrays
后未使用。
我注意到一些引用说glNormalPointer 和其他"客户端状态命令"不能包含在显示列表中。
不,它说它们不包括在显示列表中。这是真的;他们不是。
但它们的效果可能是。
gl*Pointer
命令在其命令执行后会保留指针。也就是说,指针尚未使用。仅当您使用该指针作为客户端状态调用呈现命令时,才会读取它。
使用客户端顶点数组的glDraw*
调用的行为是根据对glBegin/End
对中glArrayElement
的一系列调用来定义的,而对本身是根据对glVertex/Normal/etc
的一系列调用来定义的,使用从顶点数组读取的值。显示列表将这些glVertex/etc
呼叫记录到显示列表本身中。因此,在记录到显示列表时,使用客户端顶点数组进行渲染时,会将数组的内容记录到显示列表中。
仅当您不尝试再次读取客户端内存时,才能释放客户端内存。