September 08, 2001
Axel Kittenberger wrote:
> 
> Walter wrote:
> 
> >
> > Axel Kittenberger wrote in message <9ndn49$5ve$1@digitaldaemon.com>...
> >>Isn't the guaranteed destruction calls advertised as a major feature of C++? A lot of people even wrap certain resource binding into classes just to be sure they get freed again with destruction, when the caller leaves the scope.
> >
> > Yes, that is the C++ paradigm. Most of the resource freeing is simply memory deallocation, which is handled by the garbage collector in D. The rest can be handled with a finally block.
> 
> Okay I understand.
> 
> Well but on question, let's take in example a File stream class. Say I
> created for local use only like
> {
>    File a("cork");
>    try {
>       a.open();
>    } catch FileNotFoundException() {
>       printf("File 'cork' not found\n");
>       exit(-1);
>    }
>    a.write("bork");
> }
> 
> So the file descriptior a uses is a (limited) resource. No matter what will happen, sooner or later when the code moves out of context the resource is freed. Now I guess the file descriptior for 'a' will then stay open, right? Normally C++ classes close it's file descriptor if they were forgotten to left open.

  I would assume that the file would be closed whenever garbage
collection runs.  If you need the guarantee that it will be when you
leave a given scope, then close it in a finally block.

> Other question if the close fails, a FileIOException should be raised, so are finalizers allowed raise exceptions? I think in combination with a GC this is nearly impossibile, since the exception would be raised you anywhere from where the code currently executes.

	C++ really couldn't deal with exceptions in destructors either since an
exception could trigger an exception and the language would have to
decide with exception was more important.  The C++ solution was to
bomb.  You had to call uncaught_exception() in the destructor to
determine if it was safe to throw an exception.
	I suppose you wouldn't want to let the finalizer do anything that you
had to verify happened, or that you have to guarantee the timing of.  I
am very fond of the C++ paradigm, but I don't think the lack of it is a
show stopper.  Some might argue that using destructors to run code is
bad for one reason or another, but I'm not one of them.

Dan
September 08, 2001
a wrote in message <3B9A77F3.F62BC5BE@b.c>...
>What
>happens here?
>
> char foo[];
> foo = "Hi there!";              // 9 character string
> char bar[] = foo;               // we share it
> foo.length = foo.length - 1;    // now foo is 8 char, possibly a word
>boundary
> bar[8];                         // could this now be unallocated space?
>
>I guess I'm not sure of the specifics here, but it seems that after a decrease in size, that a part of unallocated or (worse) reallocated memory could still be accessed.  My best guess here is to never actually shrink the allocated memory whether or not it is unused, but that could create other nasty memory leaks.


The memory leak issue won't happen, because the garbage collected realloc does not just free the old storage. It will only free it if no other references to it exist.




September 08, 2001
Axel Kittenberger wrote in message <9ne3ak$c9g$1@digitaldaemon.com>...
>So the file descriptior a uses is a (limited) resource. No matter what will happen, sooner or later when the code moves out of context the resource is freed. Now I guess the file descriptior for 'a' will then stay open, right? Normally C++ classes close it's file descriptor if they were forgotten to left open.

This is not a huge problem because a (good) operating system will reclaim any resources left dangling by an aborted app. Some notorious operating systems do not, like Win95. Oops. How this is dealt with is to force finalizers to all get run on exit.

>Other question if the close fails, a FileIOException should be raised, so are finalizers allowed raise exceptions? I think in combination with a GC this is nearly impossibile, since the exception would be raised you anywhere from where the code currently executes.

That's a great question. I don't have a great answer <g>. I can think of several possibilities, but this clearly needs more work.



September 08, 2001
Axel Kittenberger wrote in message <9ne3ak$c9g$1@digitaldaemon.com>...
>So the file descriptior a uses is a (limited) resource. No matter what will happen, sooner or later when the code moves out of context the resource is freed. Now I guess the file descriptior for 'a' will then stay open, right? Normally C++ classes close it's file descriptor if they were forgotten to left open.

This is not a huge problem because a (good) operating system will reclaim any resources left dangling by an aborted app. Some notorious operating systems do not, like Win95. Oops. How this is dealt with is to force finalizers to all get run on exit.

>Other question if the close fails, a FileIOException should be raised, so are finalizers allowed raise exceptions? I think in combination with a GC this is nearly impossibile, since the exception would be raised you anywhere from where the code currently executes.

That's a great question. I don't have a great answer <g>. I can think of several possibilities, but this clearly needs more work. My first thought is design your destructors so they don't throw exceptions. My second thought is go ahead and let them throw exceptions. My third thought is use finalizers to free up resources reliably rather than destructors.

I agree that the whole "finalize on gc" approach suffers from some intractable problems in trying to deal with it perfectly. But in normal use and with a little care, these problems shouldn't be disruptive in practice.





September 10, 2001
"Walter" <walter@digitalmars.com> wrote in message news:9ndu2o$9ud$1@digitaldaemon.com...

> Yes, that is the C++ paradigm. Most of the resource freeing is simply
memory
> deallocation, which is handled by the garbage collector in D. The rest can be handled with a finally block.

Would this be a crazy feature, you could allocate objects on the heap based on a closure, maybe with some syntactic sugar that indicates that when the closure ends, the object's destructor is automatically called. This would indeed make it possible to write small objects that save and restore state, those are really handy (the constructor saves state, the destructor restores it). --Kent



September 11, 2001
Kent Sandvik wrote in message <9nj752$6li$1@digitaldaemon.com>...
>Would this be a crazy feature, you could allocate objects on the heap based on a closure, maybe with some syntactic sugar that indicates that when the closure ends, the object's destructor is automatically called. This would indeed make it possible to write small objects that save and restore state, those are really handy (the constructor saves state, the destructor
restores
>it). --Kent


Then it would be C++ <g>.


September 12, 2001
"Walter" <walter@digitalmars.com> wrote in message news:9njsqc$iis$1@digitaldaemon.com...
>
> Kent Sandvik wrote in message <9nj752$6li$1@digitaldaemon.com>...
> >Would this be a crazy feature, you could allocate objects on the heap
based
> >on a closure, maybe with some syntactic sugar that indicates that when
the
> >closure ends, the object's destructor is automatically called. This would indeed make it possible to write small objects that save and restore
state,
> >those are really handy (the constructor saves state, the destructor
> restores
> >it). --Kent
>
>
> Then it would be C++ <g>.

But the diff is that the object is placed on the heap, i.e. none of those stack related issues. Actually even something like

MyClass class; //rather than using new

would indicate that this object will we wiped out, the destructor is called, when the closure ends. --Kent



September 13, 2001
Kent Sandvik wrote in message <9nobih$f9$1@digitaldaemon.com>...
>But the diff is that the object is placed on the heap, i.e. none of those stack related issues. Actually even something like
>
>MyClass class; //rather than using new
>
>would indicate that this object will we wiped out, the destructor is
called,
>when the closure ends. --Kent


That is an interesting thought. -Walter


September 21, 2001
Just found this thread.. but you could handle this java'esq

give arrays another property called capacity.

int[] dyn;

dyn.capacity = 500
dyn.length   = 100

dyn[] = 1;

dyn.length     = 200
dyn[101...500] = 2

not sure if the array slice can be an lvalue.

Regardless you get control of the allocation and control of the data.

-Chris


Russell Borogove wrote:

> 
> 
> Walter wrote:
>> 
>> "Russell Borogove" <kaleja@estarcion.com> wrote in message news:3B97D5B9.9FF40BD7@estarcion.com...
>> > I think I'm in favor. Is there any other way to resize an array already provided?
>> 
>> The current way is to new a new array and copy the contents of the old one.
> 
> There are cases where you have a very large array in an "unpacked" or otherwise wasteful format, and you want to convert the data in place to a more compact format. In this case, if you have to create a new array and compact-on-copy, you might be spending more memory than you want to in the intermediate case. (Obviously, to make this work, your data-typing has to be fairly weak.) With a truncating resize, you can get through a memory-tight situation that you can't survive otherwise.
> 
>> Such always seemed like too much fiddling to me, and fiddling code is just more code that harbors bugs. The three choices are:
>> 
>>     array.length = newlength;
>> 
>>     array = renew(array, newlength, array[0].size);
>> 
>>     array.setLength(newlength);
>> 
>> I am leaning towards the first because it is simpler and so less prone to bugs. What I don't like about it is it appears to be a simple assignment, but is not.
> 
> *nod*
> 
> Russ Lewis wrote:
>> 
>> 4th option:
>> array.append(int[10]);
> 
> But this doesn't offer a truncation semantic.
> 
> -RB
> 

September 21, 2001
Oops I already have a bug... the lvalue should throw an array out of bounds.. off the topic though.

-Chris

Chris Holland wrote:

> Just found this thread.. but you could handle this java'esq
> 
> give arrays another property called capacity.
> 
> int[] dyn;
> 
> dyn.capacity = 500
> dyn.length   = 100
> 
> dyn[] = 1;
> 
> dyn.length     = 200
> dyn[101...500] = 2
> 
> not sure if the array slice can be an lvalue.
> 
> Regardless you get control of the allocation and control of the data.
> 
> -Chris
> 
> 
> Russell Borogove wrote:
> 
>> 
>> 
>> Walter wrote:
>>> 
>>> "Russell Borogove" <kaleja@estarcion.com> wrote in message news:3B97D5B9.9FF40BD7@estarcion.com...
>>> > I think I'm in favor. Is there any other way to resize an array already provided?
>>> 
>>> The current way is to new a new array and copy the contents of the old one.
>> 
>> There are cases where you have a very large array in an "unpacked" or otherwise wasteful format, and you want to convert the data in place to a more compact format. In this case, if you have to create a new array and compact-on-copy, you might be spending more memory than you want to in the intermediate case. (Obviously, to make this work, your data-typing has to be fairly weak.) With a truncating resize, you can get through a memory-tight situation that you can't survive otherwise.
>> 
>>> Such always seemed like too much fiddling to me, and fiddling code is just more code that harbors bugs. The three choices are:
>>> 
>>>     array.length = newlength;
>>> 
>>>     array = renew(array, newlength, array[0].size);
>>> 
>>>     array.setLength(newlength);
>>> 
>>> I am leaning towards the first because it is simpler and so less prone to bugs. What I don't like about it is it appears to be a simple assignment, but is not.
>> 
>> *nod*
>> 
>> Russ Lewis wrote:
>>> 
>>> 4th option:
>>> array.append(int[10]);
>> 
>> But this doesn't offer a truncation semantic.
>> 
>> -RB
>> 
> 
>