December 17, 2012
I am somewhat confused by some things that are being talked about in this thread.

Mike Parker said that this Image is handled by GC. Would that mean that any class members are handled by the GC too? If so, wouldn't the sfImage* be collected by the GC?

If not, and you DO need to manually delete the pointer, is there anything wrong with something like:

~this
{
    destroy(image);
}


I am just thinking that it would suck to have to manually call destroy/delete on each object before exiting main. I tested this, and I didn't get any memory errors, so I can assume it is working? I did get an error if I used delete image, however. What's the difference between the two?

On Monday, 17 December 2012 at 07:25:06 UTC, Jacob Carlborg wrote:
> C. Use a struct and call a destroy/delete function in its destructor.

And how does calling destroy/delete in a struct destructor differ from doing the same in a class destructor? I too would like to make sure I am not getting any memory leaks!


On 2012-12-17 07:45, Nekroze wrote:
>Sorry about not posting on the derelict forums, i cant remember exactly what happened but i made an account and it said i have to wait for authentication or something so i couldn't post... may have it confused with another forum but yeah will do in the future when i can post there.

It was a different forum. I got the same error that you did on the same forum. Nice to know there's this one dedicated to Derelict! I just made an account, so I'll see you in there!
December 17, 2012
On Monday, 17 December 2012 at 08:23:02 UTC, Jeremy DeHaan wrote:
> I am somewhat confused by some things that are being talked about in this thread.
>
> Mike Parker said that this Image is handled by GC. Would that mean that any class members are handled by the GC too? If so, wouldn't the sfImage* be collected by the GC?

Any class members that are allocated on the D heap, sure. But the memory for sfImage is allocated by sfml outside of the D garbage collector's heap. The GC knows nothing about it. The GC can only free the memory it controls. When you allocate memory from a C library, you are responsible for cleaning it up. But, you cannot rely on a class destructor to do this for you. There is absolutely no guarantee about when or if class destructors will be run, or in what order, during program execution. So relying on a destructor is totally nondeterministic.

And when using Derelict, if you try to call a bound library in a destructor, but the object is not released until the GC cleans up at program exit, you will always get a crash because Derelict will have already unloaded

>
> If not, and you DO need to manually delete the pointer, is there anything wrong with something like:
>
> ~this
> {
>     destroy(image);
> }
>

See above. You should never do this sort of thing in a destructor.

>
> I am just thinking that it would suck to have to manually call destroy/delete on each object before exiting main. I tested this, and I didn't get any memory errors, so I can assume it is working? I did get an error if I used delete image, however. What's the difference between the two?

I'm not quite sure what you are referring to when you say, "I tested this." Which? Freeing the image in a destructor?

I always clean up manually. When making a game in D, this is the approach I take.
==================
module mygame;
private void init()
{
// Throw Error on failure
DerelictFoo.load();
graphicsInit();
audioInit();
...
}

private void term()
{
// Release all resources here
...
audioTerm();
graphicsTerm();
}

void main(string[] args)
{
scope(exit) term();
init();
gameLoop();
}
=================

Then in each subsystem, there's always some sort of list/manager/registry that managers different objects. Each of these will have initialize/terminate method/free functions, and all of the objects they track that need to cleanup will have a terminate method. For example, I might have an aa in the graphics module that serves as a texture registry. And each texture will have a terminate method that calles into OpenGL to delete a texture.

=========
private Texture[string] _texRegistry;

class Texture
{
    private uint id;
    public void term()
    {
        glDeleteTextures(1, &id);
    }
}

void gfxTerm()
{
    if(!DerelictGL3.isLoaded) return;

    foreach(tex; _texRegistry.byValue)
        tex.term();
    clear(_texRegistry);
}
=========

The scope(exit) in the main method ensures that this termination chain is run every time the app exits regardless of the reason -- even when the Derelict libraries fail to load. So, if I'm going to be calling into the bound libraries in any of the termination functions, then at the top of the manager-level terminators I test to make sure the lib is loaded. If it isn't, I exit quick. Because loading the libraries is always the very first thing I do, if the libraries aren't loaded then there aren't going to be any resources to release.

For any short lived objects, I still don't rely on destructors but call the terminator manually. Perhaps it's my years of programming in C without ctors and dtors, but I find this process painless and just as easy as using a destructor.
December 17, 2012
On 2012-12-17 09:23, Jeremy DeHaan wrote:

> And how does calling destroy/delete in a struct destructor differ from
> doing the same in a class destructor? I too would like to make sure I am
> not getting any memory leaks!

Because there are guarantees how and when a destructor for a struct is called. You cannot rely on a destructor for a class when it's called, in what order they are called or if they're called at all.

import std.stdio;

struct Foo
{
    ~this () { writeln("destroying Foo"); }
}

class Bar
{
    ~this () { writeln("destroying Bar"); }
}

void foobar ()
{
    auto foo = Foo();
    auto bar = new Bar();
    // the destructor of "foo" _will always_ be called here
    // the destructor of "bar" _may_ be called here
}

void main ()
{
    foobar();
}

-- 
/Jacob Carlborg
December 17, 2012
Thanks for all the info, Mike. I come from a C# background, so I have pretty much 0 experience when it comes to handling memory myself(let alone working with a binding to another language) and I haven't read my D book as much as I would like.

> I'm not quite sure what you are referring to when you say, "I tested this." Which? Freeing the image in a destructor?

I tried putting destroy in the destructor like the code I wrote. Like I said, it gave me no memory errors, but I don't actually know if it even does anything. I honestly think that it is weird to not be able to rely on destructors like this. To me, it makes sense that the destructor would be a part of the garbage collection, but again I don't have any sort of experience with memory management. I find it kind of silly to have something like a destructor built into a language, but it not being reliable and more or less something to be completely ignored altogether. I do understand that in most cases this can be so, as the GC will free up the memory itself, but in some cases it could be useful to know your destructor will free up the resources the GC can't.


> The scope(exit) in the main method ensures that this termination chain is run every time the app exits regardless of the reason

This is good to know. I read about this, but haven't used it yet. Wouldn't the destructors get called at this point?



Also, what about something like this?

void main(string[] args)
{
   {
      init();
      gameLoop();
   }<-Wouldn't the destructors get called here? Or would the GC run first?
}<-And what would happen here? Would GC be run again after the scope is left?


I am just trying to understand the language better. So far it seems that the only way to prevent memory leaks when memory is being allocated outside of D is to manually delete those objects yourself and to not rely on the destructors. I will make sure this happens in the future!

Sorry if I say silly things. I am but a young programmer trying to gain knowledge!
December 17, 2012
On Monday, 17 December 2012 at 09:52:08 UTC, Jacob Carlborg wrote:
> On 2012-12-17 09:23, Jeremy DeHaan wrote:
>
>> And how does calling destroy/delete in a struct destructor differ from
>> doing the same in a class destructor? I too would like to make sure I am
>> not getting any memory leaks!
>
> Because there are guarantees how and when a destructor for a struct is called. You cannot rely on a destructor for a class when it's called, in what order they are called or if they're called at all.
>
> import std.stdio;
>
> struct Foo
> {
>     ~this () { writeln("destroying Foo"); }
> }
>
> class Bar
> {
>     ~this () { writeln("destroying Bar"); }
> }
>
> void foobar ()
> {
>     auto foo = Foo();
>     auto bar = new Bar();
>     // the destructor of "foo" _will always_ be called here
>     // the destructor of "bar" _may_ be called here
> }
>
> void main ()
> {
>     foobar();
> }

Thanks! This is also good to know!

Does that mean that putting some form of delete in a struct destructor will be called to delete contents or is that still considered unsafe?


And why don't classes have the same guarantee? Is it because they are a reference type and thus handled by the GC rather than being a value type?
December 17, 2012
On Monday, 17 December 2012 at 10:56:23 UTC, Jeremy DeHaan wrote:
> Does that mean that putting some form of delete in a struct destructor will be called to delete contents or is that still considered unsafe?
>
>
> And why don't classes have the same guarantee? Is it because they are a reference type and thus handled by the GC rather than being a value type?

Structs have their destructors called, as far as i understand, as soon as you go out of the scope they are defined in. Not sure how that works with structs that are members of a class but i assume that has the same problems as a class's destructor.

Classes don't have this guarantee because when they go out of scope, again as far as i understand, they are just added to the gc list of things that may need to be cleared (presuming they are not stored elsewhere still?) and are cleaned whenever the GC feels like it.

Now what i was thinking as a solution, would it be possible to manually run the GC cleanup pass at the end of main this way we know that the GC cleanup would run before main exits and thus sfml gets unloaded. Although i believe this still doesn't guarantee that it will think the class is fit for deconstruction at that point so it may still no work but just a thought.
December 17, 2012
On Monday, 17 December 2012 at 12:08:29 UTC, Nekroze wrote:
> Now what i was thinking as a solution, would it be possible to manually run the GC cleanup pass at the end of main this way we know that the GC cleanup would run before main exits and thus sfml gets unloaded. Although i believe this still doesn't guarantee that it will think the class is fit for deconstruction at that point so it may still no work but just a thought.

By this i mean core.memory.GC.collect() for example. Note i have never used core.memory to touch the gc or anything and am assuming this function does what i am talking about.
December 17, 2012
On Monday, 17 December 2012 at 10:39:56 UTC, Jeremy DeHaan wrote:
>>
> I tried putting destroy in the destructor like the code I wrote. Like I said, it gave me no memory errors, but I don't actually know if it even does anything. I honestly think that it is weird to not be able to rely on destructors like this. To me, it makes sense that the destructor would be a part of the garbage collection, but again I don't have any sort of experience with memory management. I find it kind of silly to have something like a destructor built into a language, but it not being reliable and more or less something to be completely ignored altogether. I do understand that in most cases this can be so, as the GC will free up the memory itself, but in some cases it could be useful to know your destructor will free up the resources the GC can't.

I've not yet used destroy and am not familiar with everything it does, but I do know that it isn't going to help you with an sfImage because the memory for that was not allocated by the GC.

What I do know about destroy is that if you do want some control over when destructors are called then destroy is what you would use to do it. destroy(myClassInstance) will call the destructor of the object. But, it will not deallocate the object's memory. Unlike the deprecated delete, object destruction and memory deallocation have been decoupled with destroy.

However, if you are going to take this route, then you have to make sure that every object which releases resources in its destructor is manually destroyed. This is no different than what I do with my term() methods. But I like my approach better. All objects have destructors, but only those that need to release resources have a term() method, so I'm less likely to make silly mistakes at 3 am after several hours of coding.

At any rate, unreliable destructors are usually what you get when you are using a GCed language (or none at all, like in Java). They're not completely useless, though.

>
>
>> The scope(exit) in the main method ensures that this termination chain is run every time the app exits regardless of the reason
>
> This is good to know. I read about this, but haven't used it yet. Wouldn't the destructors get called at this point?

No. Whatever code you have in the scope block gets called.

import std.stdio;

scope(exit) writeln("Foo");

scope(success)
{
   writeln("Bar");
   writeln("Baz");
}

All that's happening here is that the code you've included in the scope blocks will be called. The first block will execute no matter how the scope exits. The second block will only execute when the scope exits normally (and not due to an exception). The output will be:

Bar
Baz
Foo

Because the scope blocks are always executed in the reverse order they are encountered. scope(failure) will run when exiting due to an error.

So with these statements, there's nothing going on under the hood to call destructors or release memory.

>
>
>
> Also, what about something like this?
>
> void main(string[] args)
> {
>    {
>       init();
>       gameLoop();
>    }<-Wouldn't the destructors get called here? Or would the GC run first?
> }<-And what would happen here? Would GC be run again after the scope is left?

The main method in your D module is not the program entry point. The real entry point is in DRuntime. See the dmain2.d module in the Druntime source. At line 367 (in the current master) you'll see the entry point.

https://github.com/D-Programming-Language/druntime/blob/master/src/rt/dmain2.d#L367

extern (C) int main(int argc, char **argv)
{
    return _d_run_main(argc, argv, &_Dmain);
}

Looking in _d_run_main, you'll see a bit of platform-specific set up code for each platform, then a series of inner functions. At the bottom of _d_run_main is this line:

tryExec(&runAll);

runAll is an innder function inside _d_run_main, defined just above this tryExec call. It looks like so:

    void runAll()
    {
        gc_init();
        initStaticDataGC();
        rt_moduleCtor();
        rt_moduleTlsCtor();
        if (runModuleUnitTests())
            tryExec(&runMain);
        else
            result = EXIT_FAILURE;
        rt_moduleTlsDtor();
        thread_joinAll();
        rt_moduleDtor();
        gc_term();
    }

It initializes the GC, then calls the module constructors, then runs unit tests, then calls your main function. When your main function returns, module destructors are run, then gc_term is called to finalize the GC. It is here that any objects still hanging around in the GC that have not be destructed will have their destructors called and then all the memory is released.



>
>
> I am just trying to understand the language better. So far it seems that the only way to prevent memory leaks when memory is being allocated outside of D is to manually delete those objects yourself and to not rely on the destructors. I will make sure this happens in the future!

It's not the only way, but it's the easiest way.

>
> Sorry if I say silly things. I am but a young programmer trying to gain knowledge!
December 17, 2012
On Monday, 17 December 2012 at 12:08:29 UTC, Nekroze wrote:
>
> Structs have their destructors called, as far as i understand, as soon as you go out of the scope they are defined in. Not sure how that works with structs that are members of a class but i assume that has the same problems as a class's destructor.

Structs are stack objects (unless you allocate them with new and get a pointer). Stack objects will always have their destructors called when their scope exits. It's the only time you can rely on a destructor.

What is the scope of a struct that is a member of a class? I haven't tested it (I generally don't use struct destructors) but I would guess that when the class destructor is run, any structs that are members are also destructed. But not before then.

The same cannot be said of class instances that are class members, because they are also GCed object. Given class A a,  which has a member instance of class B b, once 'a' is no longer referenced by the program, it does not mean that 'b' is also no longer referenced. There could be another reference to it somewhere else. So its eventual destruction will be completely independent from that of 'a'. Which is why you should never do anything like this:

~this()
{
   destroy(b);
}

>
> Classes don't have this guarantee because when they go out of scope, again as far as i understand, they are just added to the gc list of things that may need to be cleared (presuming they are not stored elsewhere still?) and are cleaned whenever the GC feels like it.

Class instances are marked for deallocation when the GC determines that there are no more references to them. Every time you allocate more memory, the GC will decide if it needs to free up any previously allocated memory. Different GCs will use different algorithms for this, so there's no way to have any influence over which objects are deallocated when.

>
> Now what i was thinking as a solution, would it be possible to manually run the GC cleanup pass at the end of main this way we know that the GC cleanup would run before main exits and thus sfml gets unloaded. Although i believe this still doesn't guarantee that it will think the class is fit for deconstruction at that point so it may still no work but just a thought.

There's no reason to do that. If you have any external resources to cleanup, just clean it up yourself. The init/term pattern I posted earlier works just fine.
December 17, 2012
On Monday, 17 December 2012 at 14:06:30 UTC, Mike Parker wrote:
>> Now what i was thinking as a solution, would it be possible to manually run the GC cleanup pass at the end of main this way we know that the GC cleanup would run before main exits and thus sfml gets unloaded. Although i believe this still doesn't guarantee that it will think the class is fit for deconstruction at that point so it may still no work but just a thought.
>
> There's no reason to do that. If you have any external resources to cleanup, just clean it up yourself. The init/term pattern I posted earlier works just fine.

I understand that your method would work and that's fair enough but as people have indicated they still want to keep GC feel across their code rather then some parts that need manual destruction or termination and other things that don't so i was thinking this may be a way of doing that.

Just cause there is another way of doing it doesn't mean i don't want to know if the way i thought of is possible or not.

Maybe since there (practically) has to be a manual destroy method when people are making these wrappers in D for things like SFML, if they still want to have the appearance or feeling of it still using the same GC'd scheme like the rest of D is to implement some kind of reference counting in the wrapper that is transparent so that to the user it seems like the rest of D.

I am not interested in making a OO SFML wrapper myself but it seems some of the responders are so i am just trying to help in whatever limited way i can.