Colton
Colton

Reputation: 1297

Memory leak when setting texture = new Texture2D(...)

I have the following code as part of a game:

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.Black);

        spriteBatch.Begin();

        terrainSprite.Draw(spriteBatch);

        if (resourceMap.pixels.IsDisposed == false)
        {
            resources.Draw(spriteBatch, spriteFont);
        }

        spriteBatch.End();

        base.Draw(gameTime);

       //Disposes the texture here:
        resources.pixels.Dispose();
    }

    //In the resources class
    public void Update()
    {       
        //gD = graphics device
        pixels = new Texture2D(gD, 800, 353);

        //big update method
        //manipulate the pixels texture
    }

When I open task manager and look at the resource monitor, the memory usage for 'myGame.exe' is constantly going up by about 8 KB (I realize this is small, but my game holds a LOT of data, so saving every bit I can is important, and it builds up fairly quickly). This is after all other code is commented out except for what is shown here. Then, when I comment out the code: "pixels = new Texture2D(gD, 800, 353);", the memory usage stays constant. I also tried GC.Collect(), but no dice.

Is there anything else I can do to try and stop it? (Sorry, getting rid of the code is not an option :p, renewing the texture is much faster than any other method I've come across to make the texture go blank)

Upvotes: 0

Views: 1907

Answers (2)

Sebastien Poivre
Sebastien Poivre

Reputation: 31

It appears that Texture2D are not fully handled by the garbage collector.

So when you stop using it (when reusing a variable referencing it, like here, or during the OnDestroy callback), you have to manually destroy the texture. Here :

if(pixels != null) {
  Destroy(pixels);
}
pixels = new Texture2D(gD, 800, 353);

Upvotes: 0

user155407
user155407

Reputation:

Depending on your Game configuration and really, many other factors, such as how slow everything is running, etc., Update and Draw are not perfectly synchronous with each other and are not guaranteed to be run in the following fashion:

Update
Draw
Update
Draw
Update
Draw
Update
Draw
....

Therefore, since you're Disposeing in one and creating a brand new one in the other, something like this can definitely happen:

Update: create new
Update: create new //PREVIOUS ONE LEAKED!
Draw: disposes only current
Update: create new
Update: create new //AGAIN LEAK
Draw: disposes only current
...

Thus, do not Dispose separately in this fashion; Dispose one time for each new one created, no matter what.

I should also add on that textures, along with some other XNA classes (sound and music, and Effects, to name a few) are unmanaged resources, meaning the GC does not see them at all. You must call Dispose on these.

As Andrew points out in his comment, the best way to avoid these pitfalls is not to recreate textures so often - simply reuse the same one and modify it as you see fit.

Upvotes: 2

Related Questions