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

Author Topic: GC Problem with RenderImage...  (Read 4296 times)

0 Members and 1 Guest are viewing this topic.

Xeon06

  • Jr. Member
  • **
  • Posts: 58
    • View Profile
GC Problem with RenderImage...
« on: March 02, 2010, 03:06:32 am »
Okay, here we go again, this time I hope it'll be less of a headache :D.

The following code draws a white rectangle instead of the blue one it should. The reason is that the RenderImage entity in Test's constructor is garbage collected.
Code: [Select]

using System;
using SFML.Graphics;
using SFML.Window;

namespace SFMLSandbox
{
class Program
{
static void Main()
{
RenderWindow app = new RenderWindow(new VideoMode(500, 500), "SFML Sandbox");
app.Closed += new EventHandler(OnClosed);

Test test = new Test();
GC.Collect();

while(app.IsOpened())
{
app.DispatchEvents();
app.Clear();

test.Draw(app);

app.Display();
}
}

static void OnClosed(object sender, EventArgs e)
{
((RenderWindow)sender).Close();
}
}

class Test
{
public Sprite sprite;

public Test()
{
RenderImage i = new RenderImage(500, 500);
i.Clear(Color.Blue);
i.Display();
sprite = new Sprite(i.Image);
}

public void Draw(RenderTarget target)
{
target.Draw(sprite);
}
}
}

My guess is it has something to do with weak references or whatever, this stuff is over my head. If I declare the RenderImage outside of the method (but still inside the class), it works as expected:
Code: [Select]

using System;
using SFML.Graphics;
using SFML.Window;

namespace SFMLSandbox
{
class Program
{
static void Main()
{
RenderWindow app = new RenderWindow(new VideoMode(500, 500), "SFML Sandbox");
app.Closed += new EventHandler(OnClosed);

Test test = new Test();
GC.Collect();

while(app.IsOpened())
{
app.DispatchEvents();
app.Clear();

test.Draw(app);

app.Display();
}
}

static void OnClosed(object sender, EventArgs e)
{
((RenderWindow)sender).Close();
}
}

class Test
{
public Sprite sprite;
RenderImage i;

public Test()
{
i = new RenderImage(500, 500);
i.Clear(Color.Blue);
i.Display();
sprite = new Sprite(i.Image);
}

public void Draw(RenderTarget target)
{
target.Draw(sprite);
}
}
}


Is this an actual bug or am I just using this wrong?

Thanks.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
GC Problem with RenderImage...
« Reply #1 on: March 02, 2010, 07:57:19 am »
This is because the C++ RenderImage deletes its image when it is destroyed.

I don't think that I can modify this behaviour in the .Net binding, so you'd better keep your RenderImage alive as long as you use its image, or store your own copy of the image if you don't need the render image anymore (the Image class has a constructor that performs a deep copy).

It's still dangerous though, because people can still keep references to objects that are internally destroyed (not even collected by the GC, but destroyed in the C++ core) in some classes like Font or RenderImage. I don't know what I could do to prevent that. I guess that this is what happens when you mix together two languages that handle objects storage and lifetime differently :)
Laurent Gomila - SFML developer

Xeon06

  • Jr. Member
  • **
  • Posts: 58
    • View Profile
GC Problem with RenderImage...
« Reply #2 on: March 02, 2010, 03:23:12 pm »
Thanks a lot, doing a deep copy does it! :P

As for what to do to prevent this, in my opinion, the only thing to do is to make sure this is well documented when SFML 2 is released for public. :lol:

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
GC Problem with RenderImage...
« Reply #3 on: March 02, 2010, 03:26:01 pm »
Quote
As for what to do to prevent this, in my opinion, the only thing to do is to make sure this is well documented when SFML 2 is released for public

Yep ;)
Laurent Gomila - SFML developer

 

anything