ThatsGobbles's picture

System.AccessViolation when trying to delete textures at game shutdown

Hello all, I have a Texture2D class I've created, which handles creating and drawing textures. I added a destructor to the class to call GL.DeleteTexture, which looks like this at the moment:

~Texture2D() {
    GL.DeleteTexture(textureID);
}

This works fine when textures are created and destroyed normally throughout the course of the game, but when I try to shut the game down, I get a System.AccessViolation exception saying that I'm trying to write to protected memory. Any ideas on what I'm doing wrong? Thanks!


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
the Fiddler's picture

The finalizer typically runs on a different thread that doesn't have access to an OpenGL context, hence the crash. You should use the disposable pattern instead and clean up resources explicitly, using the finalizer to log resource leaks:

~Texture2D() {
    Console.WriteLine("[Warning] Resource leaked: {0} (id={1})", GetType(), Id);
}

That said, all resources should be cleaned by the drivers as soon as you dispose the OpenGL context (via GameWindow.Dispose(), GLControl.Dispose() or GraphicsContext.Dispose()). The operating system should also clean up everything on process exit.

nythrix's picture
Quote:

The finalizer typically runs on a different thread that doesn't have access to an OpenGL context, hence the crash.

Fiddler, how is your upcoming "Gloo" framework dealing with this problem? Is there a way around having to call Dispose on unmanaged resources manually? I really dislike the idea.
We're probably having the same issue with CL/GL shared objects.

the Fiddler's picture

The code I posted is lifted straight out of Gloo. It is actually very similar to what SlimDX does.

The problem with finalizers, is their non-determinism. They may run before you expect them (causing a crashes) or they may not run at all. Depending on the size of the application, implementing a ResourceManager of some sort may be a better idea.

Another idea is the use of 'resurrecting' finalizers, which place the object in question into a 'to-dispose' queue that is periodically cleaned. However, this is rather brittle during process teardown and the code can get quite complex once multiple contexts start being involved. Still, it's an interesting concept.