2

This code runs every 100 ms. The memory usage just keeps increasing until it hits 1.5 GB and then it crashes.

void takeScreenShot()
{
    Surface s;
    s = CaptureScreen(); 
    pictureBox1.Image = new Bitmap(Surface.ToStream(s, ImageFileFormat.Bmp));
    s.Dispose();
}

public Surface CaptureScreen()
{
    int width = Screen.PrimaryScreen.Bounds.Width;
    int height = Screen.PrimaryScreen.Bounds.Height;
    Device device = new Device(new Direct3D(), 0, DeviceType.Hardware, IntPtr.Zero, CreateFlags.HardwareVertexProcessing, new PresentParameters(width, height));
    DisplayMode disp = device.GetDisplayMode(0);
    Surface s = Surface.CreateOffscreenPlain(device, disp.Width, disp.Height, Format.A8R8G8B8, Pool.Scratch);
    device.GetFrontBufferData(0, s);
    return s;
} 
jnm2
  • 7,960
  • 5
  • 61
  • 99
  • Is it not possible to reuse some of the objects within the `CaptureScreen` method? Like `Device` and `Surface`? What happens when it crashes? Do you get an exception or some other sort of feedback? – scheien Sep 14 '14 at 19:01
  • possible duplicate of [Finding memory leaks in a managed Win8 metro app?](http://stackoverflow.com/questions/9995164/finding-memory-leaks-in-a-managed-win8-metro-app) – Xstian Sep 14 '14 at 19:02
  • 1
    if (pictureBox1.Image != null) pictureBox1.Image.Dispose(); – Hans Passant Sep 14 '14 at 19:10
  • @HansPassant `pictureBox1.Image.Dispose()`, but otherwise this would have been my guess too. – Dirk Sep 14 '14 at 19:11

1 Answers1

5

You are creating a new device every time.

You should create the device only once, create it in your startup code once and then keep using it.

Furthermore I suspect a memory leak in Surface.ToStream() the returned stream probably needs disposing too.

       var stream = Surface.ToStream(s, ImageFileFormat.Bmp);
       pictureBox1.Image = new Bitmap(stream);
       stream.Dispose();

As Hans Passant mentioned, Bitmap needs disposing as well.

You can very easily debug memory leaks in SharpDX by a helper to make diagnostic about unreleased COM resources. Setup at the beginning of your application this variable:

SharpDX.Configuration.EnableObjectTracking = true;

When your application exit, It will a print a report of COM objects that were not properly released with the stacktrace. The class behind this is ObjectTracker.

ObjectTracker.ReportActiveObjects() can be called to print the currently used resources at runtime (even with stack trace).

thumbmunkeys
  • 20,606
  • 8
  • 62
  • 110
  • I can confirm that the Surface.ToStream() is leaking memory but how do i dispose the returned stream? – Bjorn Jacobs Sep 14 '14 at 20:01
  • see my edit, I think you are missing some basic concepts – thumbmunkeys Sep 14 '14 at 20:30
  • `var`'s just a compiler keyword, there's no such thing as "var stream". – Tarec Sep 15 '14 at 12:19
  • @Shiro I recommend to switch to SharpDx it is actively maintained – thumbmunkeys May 27 '15 at 07:56
  • @thumbmunkeys I tried using this and their ["ScreenCapture"](https://github.com/sharpdx/SharpDX-Samples/tree/master/Desktop/Direct3D11.1/ScreenCapture) example, but I got some runtime errors because of my graphic card drivers (according to a forum) and I can't get it to work – dimitris93 May 27 '15 at 08:49
  • @Shiro can you post the forum link? As SharpDX is just a directx wrapper, I'd be surprised if it would work with SlimDX if the problem is your card – thumbmunkeys May 27 '15 at 09:44
  • @thumbmunkeys This is the [error](https://camo.githubusercontent.com/a0424776e6eb72bc409ad93514110d36df2d39ee/687474703a2f2f692e737461636b2e696d6775722e636f6d2f47345354712e706e67) I get and here is the [link](http://sharpdx.org/forum/4-general/3417-type-initializer-exception-with-2-5-0-full-installer) to the forum talking about the error. (You can google `[0x887A0004], Module: [SharpDX.DXGI]`) – dimitris93 May 27 '15 at 09:46
  • @Shiro this error indicates that your graphics card doesn't support a feature: https://msdn.microsoft.com/en-us/library/windows/desktop/bb509553%28v=vs.85%29.aspx It is not related to SharpDX – thumbmunkeys May 27 '15 at 09:54
  • @thumbmunkeys I am trying to make a video screen capture program and my graphics card is a Radeon R7 260X which is probably what the average user has or higher. I find it really strange that this graphics card is missing a feature. SharpDX doesn't provide any generic way to capture the screen ? Its so much work to go through the documentation and figure out how to do it. I mean, all there should be to it is copy the data of the back buffer to a bitmap. At least that's what I think it should be. – dimitris93 May 27 '15 at 09:58
  • @Shiro graphics card drivers are up to date? – thumbmunkeys May 27 '15 at 10:04