Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: System.AccessViolation  (Read 27286 times)

0 Members and 1 Guest are viewing this topic.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: System.AccessViolation
« Reply #15 on: July 22, 2013, 09:35:46 am »
It looks like it should work fine ;D

I'll try to test it; how do you check that it leaks? With the Windows task manager or with a dedicated tool?
Laurent Gomila - SFML developer

myl

  • Jr. Member
  • **
  • Posts: 68
    • View Profile
    • Email
Re: System.AccessViolation
« Reply #16 on: July 22, 2013, 10:00:34 am »
It looks like it should work fine ;D
Great. Then we're on the same page.
I'll try to test it; how do you check that it leaks? With the Windows task manager or with a dedicated tool?
I use ANTS memory profiler, but leak is also obvious from task manager.

myl

  • Jr. Member
  • **
  • Posts: 68
    • View Profile
    • Email
Re: System.AccessViolation
« Reply #17 on: July 22, 2013, 10:09:42 am »
Correction: It seems the mem "leak" that the task manager shows is eventually garbage collected. ANTS shows a private bytes leak that goes up to 1024mb (see screenshot) and after this point, the renderwindow turns white.

myl

  • Jr. Member
  • **
  • Posts: 68
    • View Profile
    • Email
Re: System.AccessViolation
« Reply #18 on: July 22, 2013, 10:16:15 am »
FYI: The unit of the horizontal axis is minutes.

Another FYI: Inserting a texture.Dispose(); after drawing the sprite removes the leakage, but you say this shouldn't be necessary.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: System.AccessViolation
« Reply #19 on: July 22, 2013, 10:22:41 am »
Ok, thanks for the additional information.
Laurent Gomila - SFML developer

shawnliu

  • Newbie
  • *
  • Posts: 8
    • View Profile
    • Email
Re: System.AccessViolation
« Reply #20 on: July 22, 2013, 10:48:38 pm »
Hi, I will be glad to give you the answer. I am the author of xInterop NGen++ at http://www.xInterop.com, which is a C# wrapper generator for native C++ DLL. I recently wrapped SFML libraries for testing purpose. I had a similar issue with my version of SFML C# Wrapper generated by xInterop NGen++ at http://www.xinterop.com/index.php/2013/07/20/generating-sfml-c-net-wrapper-libraries-in-10-minutes-part-i/.

The cause of the issue is GC management. When you call into any C++ native DLL, you must make sure any C# instantiated object you pass to the native C++ method will not get GC-collected during the call.

The solution is to use GC.KeepAlive or using keyword(your choice) to make sure that. So, your code should like the following,

var renderWindow = new RenderWindow(new SFML.Window.VideoMode(200, 200), "I'm a leaker");
while (true)
{
    var texture = new Texture("nonprogressive.jpg");
    var sprite = new Sprite(texture);
    renderWindow.Draw(sprite);
    renderWindow.Display();
    renderWindow.DispatchEvents();
    GC.KeepAlive(texture);
    GC.KeepAlive(sprite);
    GC.Collect();
}
GC.KeepAlive(renderWindow);
 

--------------------------------------------------------------------------------
Shawn Liu, Author of xInterop NGen++ at http://www.xInterop.com.


Glad I asked then :) This minimal example is leaking full on. What am I misunderstanding?
var renderWindow = new RenderWindow(new SFML.Window.VideoMode(200, 200), "I'm a leaker");
while (true)
{
    var texture = new Texture("nonprogressive.jpg");
    var sprite = new Sprite(texture);
    renderWindow.Draw(sprite);
    renderWindow.Display();
    renderWindow.DispatchEvents();
    GC.Collect();
}
 
« Last Edit: July 22, 2013, 10:50:31 pm by shawnliu »
Shawn Liu, Author of xInterop NGen++, A C# Wrapper Generator for native C++ DLL at http://www.xInterop.com.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: System.AccessViolation
« Reply #21 on: July 22, 2013, 10:59:40 pm »
Thanks for your feedback.

The texture is correctly referenced in the sprite instance, and the sprite is used in the Draw call. In this scenario, I don't see how (when) the GC would collect one of these variables too early. When they are no longer referenced, they are not needed anymore.

And wouldn't that cause crashes rather than memory leaks?
Laurent Gomila - SFML developer

shawnliu

  • Newbie
  • *
  • Posts: 8
    • View Profile
    • Email
Re: System.AccessViolation
« Reply #22 on: July 22, 2013, 11:19:52 pm »
Being referenced in the scope does not mean much when the GC is running release mode when GC can be very aggressive. GC claim on the object could be as much as early you could think.

He did say he got AccessViolation exception if I recalled correctly.

Thanks for your feedback.

The texture is correctly referenced in the sprite instance, and the sprite is used in the Draw call. In this scenario, I don't see how (when) the GC would collect one of these variables too early. When they are no longer referenced, they are not needed anymore.

And wouldn't that cause crashes rather than memory leaks?
« Last Edit: July 22, 2013, 11:21:49 pm by shawnliu »
Shawn Liu, Author of xInterop NGen++, A C# Wrapper Generator for native C++ DLL at http://www.xInterop.com.

shawnliu

  • Newbie
  • *
  • Posts: 8
    • View Profile
    • Email
Re: System.AccessViolation
« Reply #23 on: July 22, 2013, 11:35:25 pm »
You can also use Dispose method after you are done with the object if it supports IDisposable interface.

Hi, I will be glad to give you the answer. I am the author of xInterop NGen++ at http://www.xInterop.com, which is a C# wrapper generator for native C++ DLL. I recently wrapped SFML libraries for testing purpose. I had a similar issue with my version of SFML C# Wrapper generated by xInterop NGen++ at http://www.xinterop.com/index.php/2013/07/20/generating-sfml-c-net-wrapper-libraries-in-10-minutes-part-i/.

The cause of the issue is GC management. When you call into any C++ native DLL, you must make sure any C# instantiated object you pass to the native C++ method will not get GC-collected during the call.

The solution is to use GC.KeepAlive or using keyword(your choice) to make sure that. So, your code should like the following,

var renderWindow = new RenderWindow(new SFML.Window.VideoMode(200, 200), "I'm a leaker");
while (true)
{
    var texture = new Texture("nonprogressive.jpg");
    var sprite = new Sprite(texture);
    renderWindow.Draw(sprite);
    renderWindow.Display();
    renderWindow.DispatchEvents();
    GC.KeepAlive(texture);
    GC.KeepAlive(sprite);
    GC.Collect();
}
GC.KeepAlive(renderWindow);
 

--------------------------------------------------------------------------------
Shawn Liu, Author of xInterop NGen++ at http://www.xInterop.com.


Glad I asked then :) This minimal example is leaking full on. What am I misunderstanding?
var renderWindow = new RenderWindow(new SFML.Window.VideoMode(200, 200), "I'm a leaker");
while (true)
{
    var texture = new Texture("nonprogressive.jpg");
    var sprite = new Sprite(texture);
    renderWindow.Draw(sprite);
    renderWindow.Display();
    renderWindow.DispatchEvents();
    GC.Collect();
}
 
Shawn Liu, Author of xInterop NGen++, A C# Wrapper Generator for native C++ DLL at http://www.xInterop.com.

myl

  • Jr. Member
  • **
  • Posts: 68
    • View Profile
    • Email
Re: System.AccessViolation
« Reply #24 on: July 22, 2013, 11:42:02 pm »
I can see why this thread has become a bit confusing, since maybe I should have created a new one when I started asking about memory management. The AccessViolations I experienced are unrelated to the minimal mem leak example. The AccessViolations in my own project didn't occur until I started to make attempts to eliminate leaks by overloading Texture Destructors and Calling Destroy(true) in them. It fixed the leak but caused AccessViolations.

So first things first. Let's try to fix the leak in the minimal code in a healthy way. Ideally without manually disposing textures or manually keeping them alive :)

shawnliu

  • Newbie
  • *
  • Posts: 8
    • View Profile
    • Email
Re: System.AccessViolation
« Reply #25 on: July 23, 2013, 12:07:18 am »
If that is the case you should write code like the following I posted, as I said earlier, it will also prevent GC from reclaiming the objects earlier than you expect.

using(var renderWindow = new RenderWindow(new SFML.Window.VideoMode(200, 200), "I'm a leaker"))
{
    while (true)
   {
        using(var texture = new Texture("nonprogressive.jpg"))
        using(var sprite = new Sprite(texture))
       {
            renderWindow.Draw(sprite);
            renderWindow.Display();
            renderWindow.DispatchEvents();
       }
   }
}
 
« Last Edit: July 23, 2013, 04:15:47 am by shawnliu »
Shawn Liu, Author of xInterop NGen++, A C# Wrapper Generator for native C++ DLL at http://www.xInterop.com.

myl

  • Jr. Member
  • **
  • Posts: 68
    • View Profile
    • Email
Re: System.AccessViolation
« Reply #26 on: July 23, 2013, 12:51:36 am »
That is equivalent to running texture.Dispose() and sprite.Dispose() after drawing as discussed earlier, which solves the leak. But as I understand sfml intends these to be gc'ed properly by dereference.

shawnliu

  • Newbie
  • *
  • Posts: 8
    • View Profile
    • Email
Re: System.AccessViolation
« Reply #27 on: July 23, 2013, 02:50:30 am »
The following is the original code you posted, it does not call Dispose method. Are you expecting the GC to release the texture and sprite object right after each loop with a call to GC.collect(). I don't think GC works that way as I know, I may be wrong though. Referencing and de-referencing object in GC is just a concept, I think its complication is way beyond that.

var renderWindow = new RenderWindow(new SFML.Window.VideoMode(200, 200), "I'm a leaker");
while (true)
{
    var texture = new Texture("nonprogressive.jpg");
    var sprite = new Sprite(texture);
    renderWindow.Draw(sprite);
    renderWindow.Display();
    renderWindow.DispatchEvents();
    GC.Collect();
}

Secondly, Developers are responsible for calling Dispose or using "using" keyword to call Dispose method. Otherwise, GC calls the finalizer to call Dispose if the pattern is implemented correctly.

If this is a memory issue, how much memory loss have you been seeing by running your code?

That is equivalent to running texture.Dispose() and sprite.Dispose() after drawing as discussed earlier, which solves the leak. But as I understand sfml intends these to be gc'ed properly by dereference.
Shawn Liu, Author of xInterop NGen++, A C# Wrapper Generator for native C++ DLL at http://www.xInterop.com.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: System.AccessViolation
« Reply #28 on: July 23, 2013, 07:57:43 am »
Quote
Being referenced in the scope does not mean much when the GC is running release mode when GC can be very aggressive. GC claim on the object could be as much as early you could think.
Ok, but... I don't think it can happen before the object is explicitly used in the function (i.e. before Draw(sprite)).
Laurent Gomila - SFML developer

shawnliu

  • Newbie
  • *
  • Posts: 8
    • View Profile
    • Email
Re: System.AccessViolation
« Reply #29 on: July 23, 2013, 07:48:14 pm »
I tested the same code by using "using keyword" for 1 hour using my own version of C# wrapper for SFML generated by NGen++, no memory leak, no crash. The underlying native C++ code is really robust, very stable.

I have not read the official version of C# wrapper code yet, I don't know the details, I can not comment.

If you use HandleRef in the class implementation, the object won't get reclaimed by GC during the P/Invoke call. So, you are right, it won't happen before the call, it can happen during the call if HandleRef or similar method is not used to prevent GC from reclaiming the object during the call.

Quote
Being referenced in the scope does not mean much when the GC is running release mode when GC can be very aggressive. GC claim on the object could be as much as early you could think.
Ok, but... I don't think it can happen before the object is explicitly used in the function (i.e. before Draw(sprite)).
Shawn Liu, Author of xInterop NGen++, A C# Wrapper Generator for native C++ DLL at http://www.xInterop.com.

 

anything