Jump to page: 1 2 3
Thread overview
The C heap and D.
Sep 27, 2004
Dave
Sep 27, 2004
Arcane Jill
Sep 28, 2004
Dave
Sep 29, 2004
Arcane Jill
Sep 29, 2004
Burton Radons
Sep 29, 2004
Burton Radons
Sep 29, 2004
Dave
Sep 29, 2004
Burton Radons
Sep 29, 2004
Dave
OT: Dr. Seuss
Sep 29, 2004
Regan Heath
Oct 01, 2004
Walter
Oct 01, 2004
Walter
Oct 01, 2004
Arcane Jill
Oct 01, 2004
Arcane Jill
Oct 04, 2004
Walter
Oct 05, 2004
Arcane Jill
Oct 05, 2004
Stewart Gordon
Oct 05, 2004
Ben Hinkle
Oct 05, 2004
Stewart Gordon
Oct 05, 2004
Ben Hinkle
Oct 06, 2004
Stewart Gordon
Oct 06, 2004
Ben Hinkle
Oct 06, 2004
Stewart Gordon
Oct 06, 2004
Ben Hinkle
Oct 07, 2004
Stewart Gordon
Oct 06, 2004
Kevin Bealer
September 27, 2004
Can the std.c.stdlib.malloc() and free() family of functions 'safely' be used as
they are in C for basic types and structs w/o any special interaction with the
GC (e.g.: w/o using gc.addRange())?

For example, with char* strings, or dynamic arrays of structs.

Any special considerations for malloc/free on an array of structs with GC'd members?

The docs. mention using addRange() for class allocators (using the C heap) if
the classes allocate any objects that use the GC, but the docs. don't seem to
really go beyond that.

TIA for the sanity check.


September 27, 2004
In article <cj8drs$1cj7$1@digitaldaemon.com>, Dave says...
>
>
>Can the std.c.stdlib.malloc() and free() family of functions 'safely' be used as
>they are in C for basic types and structs w/o any special interaction with the
>GC (e.g.: w/o using gc.addRange())?

Yes, provided that your mallocked memory contains no pointers to anything obtained via "new".


>For example, with char* strings, or dynamic arrays of structs.

If by "char* strings" you mean an array of chars, that will be fine. An array of pointers to chars is not. An array of structs will be okay iff the structs contain no pointers to "new"ed stuff.


>Any special considerations for malloc/free on an array of structs with GC'd members?

Well, then you'd have to call addRange().

Arcane Jill


September 28, 2004
Arcane Jill wrote:

> In article <cj8drs$1cj7$1@digitaldaemon.com>, Dave says...
>>
>>
>>Can the std.c.stdlib.malloc() and free() family of functions 'safely' be
>>used as they are in C for basic types and structs w/o any special
>>interaction with the GC (e.g.: w/o using gc.addRange())?
> 
> Yes, provided that your mallocked memory contains no pointers to anything obtained via "new".
> 
> 
>>For example, with char* strings, or dynamic arrays of structs.
> 
> If by "char* strings" you mean an array of chars, that will be fine. An array of pointers to chars is not. An array of structs will be okay iff the structs contain no pointers to "new"ed stuff.
> 
> 
>>Any special considerations for malloc/free on an array of structs with GC'd members?
> 
> Well, then you'd have to call addRange().
> 
> Arcane Jill

Thanks for the quick reply!

How about somewhat of the 'inverse' of the examples above.. e.g: The case where a GC'd class object malloc's member(s) which are subsequently free'd in the destructor?

Unless 'auto' is enforced by the class definition, I know the destructor may be called at an indeterminate time and therefore not free resources as quickly as may be desired, but in some cases I think this will be acceptable behaviour. So, other than not freeing resources immediately, are there any problems with this not covered by the standard C heap caveats?

If 'no', than I take it that four general rules of thumb can be applied here:

1) The C heap /can/ be used in D for non-aggregate native types without
special consideration of the GC. It is simply using a seperate heap.
2) struct pointers allocated with the C heap can have GC'd members if the
struct pointers are properly 'registered' with the GC.
3) If struct pointers allocated with the C heap are /not/ registered with
the GC, then all members must use the C heap as well.
4) All classes allocated with the C heap should be registered with the GC
because they can be derived from.

If so, I'll add a suggested change to the docs. to http://www.prowiki.org/wiki4d/wiki.cgi?DocComments/Memory

I think this needs to be clarified in the docs. because a lot of people coming over from C will probably find plenty of uses for the C heap, and the ability to mix GC with C heap relatively easily is a very cool feature of D, IMHO.

Thanks again.

September 29, 2004
In article <cjc0c0$2eni$1@digitaldaemon.com>, Dave says...

>Thanks for the quick reply!
>
>How about somewhat of the 'inverse' of the examples above.. e.g: The case where a GC'd class object malloc's member(s) which are subsequently free'd in the destructor?
>
>Unless 'auto' is enforced by the class definition, I know the destructor may be called at an indeterminate time and therefore not free resources as quickly as may be desired, but in some cases I think this will be acceptable behaviour. So, other than not freeing resources immediately, are there any problems with this not covered by the standard C heap caveats?

I think you got it spot on.

There is one caveat, for which I don't have a workaround. Rumor has it that if an application has global/static data, and that data happens by coincidence to "look like" the address of a GC'ed object (for example, an int whose value happens to be identical to the address of a "new"ed object) then it is, apparently, feasable that the GC will /never/ regard the object as unreachable, and /never/ call its destructor, even on program exit. would like Walter to address at some point.


>If 'no', than I take it that four general rules of thumb can be applied here:
>
>1) The C heap /can/ be used in D for non-aggregate native types without special consideration of the GC. It is simply using a seperate heap.

I think that's right.

>2) struct pointers allocated with the C heap can have GC'd members if the struct pointers are properly 'registered' with the GC.

Yup.

>3) If struct pointers allocated with the C heap are /not/ registered with the GC, then all members must use the C heap as well.

Sounds good to me.

>4) All classes allocated with the C heap should be registered with the GC because they can be derived from.

Aren't you confusing an instance with a declaration there? How can you derive from an instance? This one I don't get. I've probably misunderstood.


>If so, I'll add a suggested change to the docs. to http://www.prowiki.org/wiki4d/wiki.cgi?DocComments/Memory
>
>I think this needs to be clarified in the docs. because a lot of people coming over from C will probably find plenty of uses for the C heap, and the ability to mix GC with C heap relatively easily is a very cool feature of D, IMHO.

So long as you remember that anything mallocked must also be freed, I guess that's so.

Arcane Jill


September 29, 2004
Arcane Jill wrote:
> In article <cjc0c0$2eni$1@digitaldaemon.com>, Dave says...
> 
> 
>>Thanks for the quick reply!
>>
>>How about somewhat of the 'inverse' of the examples above.. e.g: The case
>>where a GC'd class object malloc's member(s) which are subsequently free'd
>>in the destructor?
>>
>>Unless 'auto' is enforced by the class definition, I know the destructor may
>>be called at an indeterminate time and therefore not free resources as
>>quickly as may be desired, but in some cases I think this will be
>>acceptable behaviour. So, other than not freeing resources immediately, are
>>there any problems with this not covered by the standard C heap caveats?
> 
> 
> I think you got it spot on.
> 
> There is one caveat, for which I don't have a workaround. Rumor has it that if
> an application has global/static data, and that data happens by coincidence to
> "look like" the address of a GC'ed object (for example, an int whose value
> happens to be identical to the address of a "new"ed object) then it is,
> apparently, feasable that the GC will /never/ regard the object as unreachable,
> and /never/ call its destructor, even on program exit. would like Walter to
> address at some point. 

Why would an easily-testable quality be rumour?  The GC is type-unaware, so this is true.  It doesn't require an identical match, either; it only has to alias to the span of memory allocated for the object:

    import std.gc;

    int x;

    class Foo
    {
        this () { printf ("%p feels strong!\n", this); }
        ~this () { printf ("%p's melting!\n", this); }
    }

    int main ()
    {
        x = 3 + cast (int) cast (void *) new Foo ();
        new Foo ();
        std.gc.fullCollect ();
        return 0;
    }

Prints:

    008A1FE0 feels strong!
    008A1FD0 feels strong!
    008A1FD0's melting!

An object temporarily suspended by an accidental alias will probably get terminated the next collection; I would worry more that scanning takes many times longer than it should due to the lack of type awareness, rather than a fear of an object being suspended by the GC.

Odd that the GC is never called, that's new behaviour.
September 29, 2004
Burton Radons wrote:

> Odd that the GC is never called, that's new behaviour.

Ack, odd that the destructor is never called, that is.
September 29, 2004
Arcane Jill wrote:

> In article <cjc0c0$2eni$1@digitaldaemon.com>, Dave says...
> 
[snip]
> 
> There is one caveat, for which I don't have a workaround. Rumor has it that if an application has global/static data, and that data happens by coincidence to "look like" the address of a GC'ed object (for example, an int whose value happens to be identical to the address of a "new"ed object) then it is, apparently, feasable that the GC will /never/ regard the object as unreachable, and /never/ call its destructor, even on program exit. would like Walter to address at some point.
> 

This seems to work Ok; the dtor is called both w/ & w/o 'delete a'.

#import std.gc;
#
#int i;
#
#class A {
#    int i;
#    static int j;
#    ~this()
#    {
#        printf("~dtor\n");
#    }
#}
#
#void main()
#{
#    newA();
#    printf("%x, %x\n",i,A.j);
#}
#
#void newA()
#{
#    A a;
#    i = cast(int)&a;
#    a = new A();
#    a.j = cast(int)&a;
#    printf("%p, %x, %x\n",&a,i,a.j);
#    //delete a;
#}

> 
>>If 'no', than I take it that four general rules of thumb can be applied here:
>>
>>1) The C heap /can/ be used in D for non-aggregate native types without special consideration of the GC. It is simply using a seperate heap.
> 
> I think that's right.
> 
>>2) struct pointers allocated with the C heap can have GC'd members if the struct pointers are properly 'registered' with the GC.
> 
> Yup.
> 
>>3) If struct pointers allocated with the C heap are /not/ registered with the GC, then all members must use the C heap as well.
> 
> Sounds good to me.
> 
>>4) All classes allocated with the C heap should be registered with the GC because they can be derived from.
> 
> Aren't you confusing an instance with a declaration there? How can you derive from an instance? This one I don't get. I've probably misunderstood.
> 

Something along those lines is already outlined here

http://digitalmars.com/d/memory.html#newdelete

so I'm thinking 'rule-of-thumb' 4) would apply because the original developer can't know if the class will be derived from.

> 
>>If so, I'll add a suggested change to the docs. to http://www.prowiki.org/wiki4d/wiki.cgi?DocComments/Memory
>>
>>I think this needs to be clarified in the docs. because a lot of people coming over from C will probably find plenty of uses for the C heap, and the ability to mix GC with C heap relatively easily is a very cool feature of D, IMHO.
> 
> So long as you remember that anything mallocked must also be freed, I guess that's so.

I'll add that to the suggested doc. change as well. Something along the lines of "...as with C/++, memory malloc'd must be free'd and pointers should be zeroed...", etc.

> 
> Arcane Jill

September 29, 2004
Dave wrote:
> #void newA()
> #{
> #    A a;
> #    i = cast(int)&a;

That stores the address of the container of the reference to the instance of the class A, not the address of the reference to the instance of the class A.
September 29, 2004
Burton Radons wrote:

> Dave wrote:
>> #void newA()
>> #{
>> #    A a;
>> #    i = cast(int)&a;
> 
> That stores the address of the container of the reference to the instance of the class A, not the address of the reference to the instance of the class A.

Oops - you're right. Give the following code a shot..

This /does/ apparently show what AJ describes.

W/o 'delete a;' the destructor is not called. If delete is called or the i and A.j values are changed before return from main(), the dtor is called.

#import std.gc;
#
#int i;
#
#class A {
#    int i;
#    static int j;
#    ~this()
#    {
#        printf("~dtor (%p)\n",this);
#    }
#}
#
#void main()
#{
#    newA();
#    printf("%x, %x\n",i,A.j);
#    //i = 0; A.j = 0;
#}
#
#void newA()
#{
#    A a;
#    a = new A();
#    i = cast(int)(cast(void*)a);
#    a.j = cast(int)(cast(void*)a);
#    printf("%p, %x, %x\n",a,i,a.j);
#    //delete a;
#}

September 29, 2004
On Wed, 29 Sep 2004 06:23:03 -0700, Burton Radons <burton-radons@smocky.com> wrote:
> Dave wrote:
>> #void newA()
>> #{
>> #    A a;
>> #    i = cast(int)&a;
>
> That stores the address of the container of the reference to the instance of the class A, not the address of the reference to the instance of the class A.

This is a sentence even "Dr. Seuss" would be proud of. :)

Regan

-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
« First   ‹ Prev
1 2 3