Can glDeleteLists crash?

I have code which has run well for years, which compiles static objects into display lists on first attempt to render, and deletes the display list when the object is no longer pertinent. This has worked fine forever on nVIDIA drivers version 6.34 through 21.83, as well as ATI drivers of various sorts.

When we upgraded our QA lab to nVIDIA 28.32, we’re starting to see occasional crashes inside NVOGLNT in response to the call to glDeleteLists().

I’m pretty sure the delete is legitimate, and this is an actual driver bug, and I think that IF I passed in junk data (which I believe I’m not) glDeleteLists() would set an error, rather than result in undefined behavior (i e crash). However, this is your chance to set me straight if I’m wrong, tell me you know what the problem is, share a kind word for a fellow programmer in need, etc.

From the almighty spec:

void DeleteLists( uint list, sizei range );

where list is the index of the first display list to be deleted and range is the number
of display lists to be deleted. All information about the display lists is lost, and the
indices become unused. Indices to which no display list corresponds are ignored.
If range = 0, nothing happens.

If you are absolutely sure, that the crash is caused by the glDeleteLists call, this is a driver problem.

You should maybe try to come up with a bare bones glut demonstration app that crashes nicely
The NVIDIA (all caps!) folks will surely appreciate it.

“Can” it crash? Well, obviously it can, you seem to have demonstrated that.

The interface is supposed to be safe. In fact, unlike GenTextures/DeleteTextures, GenLists/DeleteLists doesn’t even use a pointer interface. In other words, I would think that there should be absolutely zero cases in which DeleteLists should crash, even with a broken application. (If you passed a null pointer into DeleteTextures, that would be your problem, not ours.)

Of course, if you want any hope of our being able to fix this, you’re going to have to provide some sort of repro case.

  • Matt

> Of course, if you want any hope of our
> being able to fix this, you’re going to
> have to provide some sort of repro case.

Yes, I understand that. This is a 30 MB binary that seems to only do this on 28.x drivers (not earlier drivers) and only once for every 100+ machine-QA hours or so :frowning:

While this is not very OpenGL related anymore, what else can perhaps help track this down? Would deleting a list which is asynchronously being drawn be a problem? How about deleting a list which was created before the context was destroyed and re-created with ShareLists copying it between old and new context? Can you guys do anything with a minidump, or something as menial as a stack trace copied out of MSDEV?

Deleting lists that are in use by the hardware shouldn’t be a problem if things are working right.

Yes, if you give me a stack trace in hex offsets (and an exact driver version and OS) it is quite possible to identify exactly what is crashing.

Please email me that information, plus any other relevant information.

  • Matt

I have the same problem with crashes of glDeleteLists using GeForce3 with 2832 driver version.

Starting the same application in VisualStudios debug mode with same parameters and data it’s crashing sometimes - and sometimes not!!! But I found no dependencies showing me possible causes. My reliance in the “state machine” is shrinking…

The crash occures only when I use rendering threads with rendering contexts that are prepared with wglShareLists(). When glDeleteLists() is performed the RC of the graphics view as well as the RC of the thread are existing… hmm.

jwatte - now I’ll try OLDER driver versions, but it’s not the solution! But what else???

Any ideas are highly welcome!
Ralf

I have some problems with display list and memory usage too. I’m trying to render a high resolution binary voxel grid with solid cubes corresponding to active voxels. I’m loading the grid from file and create an array of display lists:

VoxelGridDispBase = glGenLists(VOXELGRIDSIZE);

Then I build each list:

  
for(int x = 0; x < VOXELGRIDSIZE - 1; x++)
{
   glNewList(VoxelGridDispBase + x,GL_COMPILE);
   ... 
   glEndList();
} 

And finally I free resources with:

glDeleteLists(VoxelGridDispBase,VOXELGRIDSIZE);

The strange thing is that looking at perfmon of Windows XP I notice that the Commited bytes to not turn to their initial value (before calling glGenLists) when I call glDeleteLists. It seems like a memory leak.Any help?

Ooh, thread from the dead.
You’re aware that you generate one list too few in the for-loop?
That shouldn’t crash glDeleteLists, it only deletes lists which would return true for glIsList.
Do you wglShareLists?
Is the leak increasing if you do this a lot of times?
If not and the difference is small, I wouldn’t be concerned. Maybe the driver allocates some data for storing display list informations when the first display list is generated and keeps that around for possible further lists until the OpenGL context is deleted?

I’m creating VOXELGRIDSIZE display lists from range
VoxelGridDispBase,VoxelGridDispBase + 1,…,VoxelGridDispBase + VOXELGRIDSIZE - 1,ok?
Actually I wrote wrongly my code.The correct code is(copy form cpp file):

 
for(int x = voxelgrid_size - 1; x>=0; x--)
{
 glNewList(VoxelGridDispBase + x,GL_COMPILE); 
 ...
 glEndList();
}

In the loop I’m counting from VOXELGRIDSIZE - 1 to 0 including 0 and add the counter to VoxelGridDispBase. So I create exactly as many lists as I generated.

I don’t use wglShareLists.Maybe if I post the whole function will help you?

 
#ifdef _BITVOXELGRID
void BuildVoxelGridDispList(const bit_vector *voxelgrid,GLint voxelgrid_size,GLfloat *voxelgrid_center,GLfloat voxelgrid_length)
#else
void BuildVoxelGridDispList(const bool *voxelgrid,GLint voxelgrid_size,GLfloat *voxelgrid_center,GLfloat voxelgrid_length)
#endif
{
	HWND hDlg = NULL;
	char message[128]={NULL};
	
	// Create progress bar Dialog box
	hDlg = CreateDialog(Hinst,MAKEINTRESOURCE(IDD_VXLPROGRESS),Hwnd,ProgressDialogProc);
 
	// Setup progress bar
	SendDlgItemMessage(hDlg,IDC_PROGRESS1,PBM_SETPOS,(WPARAM)0,0);
	SendDlgItemMessage(hDlg,IDC_PROGRESS1,PBM_SETRANGE,0,MAKELPARAM(0,voxelgrid_size));
	SendDlgItemMessage(hDlg,IDC_PROGRESS1,PBM_SETSTEP,(WPARAM)1,0);

	// Set progress bar to start
	SendDlgItemMessage(hDlg,IDC_PROGRESS1,PBM_SETPOS,(WPARAM)0,0);

	// Generate  new display lists in
	// memory  and return a pointer to them
	if(VoxelGridDispBase != 0)
		glDeleteLists(VoxelGridDispBase,voxelgrid_size);

	if(VoxelGridDispLists) delete[] VoxelGridDispLists;

	// Allocate space for display lists
	VoxelGridDispLists = new GLuint[voxelgrid_size];
		
	// clean memory
	memset(VoxelGridDispLists,0,voxelgrid_size * sizeof(GLuint));

	if(!(VoxelGridDispBase = glGenLists(voxelgrid_size)))	// generate display lists
	{
		MessageBox(Hwnd,"Could not Generate Display lists","OpenGL Error",NULL);
		// Disable Voxel Grid rendering
		EnableMenuItem(GetMenu(Hwnd),ID_VOXELIZATION_RENDER_VOXELGRID,MF_GRAYED);
	}

	GLfloat vxlCenter[3] = {0.0f , 0.0f , 0.0f};	// temp variable for storing each voxel's center

	// Render every voxel
	for(int x = voxelgrid_size - 1; x>=0; x--)
	{
		// Build message string set it 
		// to label above progress bar 
		sprintf(message,"Building Voxel Display Lists(%4.1f %%)",(100.0f - ((float)x/(float)voxelgrid_size * 100)));
		SetDlgItemText(hDlg,IDC_LABEL,message);
		SendDlgItemMessage(hDlg,IDC_PROGRESS1,PBM_STEPIT,0,0);

		if(!glIsList(VoxelGridDispBase + x))
		{
			MessageBox(Hwnd,"Not a list!!",NULL,NULL);
			break;
		}

		VoxelGridDispLists[x] = VoxelGridDispBase + x;

		glNewList(VoxelGridDispBase + x,GL_COMPILE);
		for(int y = voxelgrid_size - 1; y >= 0; y--)
			for(int z = voxelgrid_size - 1; z >= 0; z--)
			{
#ifdef _BITVOXELGRID
				if((*voxelgrid)[voxelgrid_size * voxelgrid_size * x + voxelgrid_size * y + z])
#else
				if(*(voxelgrid + voxelgrid_size * voxelgrid_size * x + voxelgrid_size * y + z))
#endif
				{
					CalcVoxelCenter(x,y,z,voxelgrid_center,voxelgrid_size,voxelgrid_length,vxlCenter);	
		  
					glTranslatef(vxlCenter[0],vxlCenter[1],vxlCenter[2]);

					glutSolidCube(voxelgrid_length / voxelgrid_size);

					glTranslatef(-vxlCenter[0],-vxlCenter[1],-vxlCenter[2]);
		  
				}/*
				else	// useful debugging code do NOT DELETE
				{
					glColor3f(0.5f,0.5f,0.5f);

					CalcVoxelCenter(x,y,z,vgrid_center,vgrid_length,vxlCenter);	
		  
					glTranslatef(vxlCenter[0],vxlCenter[1],vxlCenter[2]);

					glutWireCube(vgrid_length / VOXELGRIDSIZE);

					glTranslatef(-vxlCenter[0],-vxlCenter[1],-vxlCenter[2]);
				}*/
			}
			glEndList(); 
	}

	// Set progress bar to 100%
	SendDlgItemMessage(hDlg,IDC_PROGRESS1,PBM_SETPOS,(WPARAM)voxelgrid_size,0);

	// Close Dialog box
	if(hDlg) DestroyWindow(hDlg);
}
 

Finally I delete like this:

 
if(VoxelGridDispBase != 0)
						{
							glDeleteLists(VoxelGridDispBase,VOXELGRIDSIZE);							
							VoxelGridDispBase = 0;
						}

if(VoxelGridDispLists)
						{
							delete[] VoxelGridDispLists;
							VoxelGridDispLists = NULL;
						}
 

I see no memory leak from looking at the code.
What’s the size of the leak?
What are the answers to my previous questions?

One thing is numerically dangerous:
glTranslatef(+);
Cube();
glTranslatef(-);
could accumulate rounding errors.
Use
glPushMatrix();
glTranslatef(+);
Cube();
glPopMatrix();
instead.

Actually it would be much faster if you would not use the glTranslate at all and only put the cubes geometry at the translated position into the display lists. (Write your own cube function.)

Thanks a lot Relic. Actually the only way to show you the “leak” is to capture a screen from perfmon. I’ll try to measure the amount of bytes that stay commited when I delete the display lists. The weird thing is that when I allocate a new array of display lists the commited bytes do not surpass the previous peak value. So the total commited bytes doesn’t get higher as I repeat the process. Simply it does not fall to the initial value before the first array is allocated. I hope I’ll find out why. Thanks again for your help. OpenGL.org rocks big time!