An alternative to .init

downs default_357-line at yahoo.de
Tue Sep 9 07:56:17 PDT 2008


Andrei Alexandrescu wrote:
> What's the deal with destroyed but not deleted? Consider:
> 
> int[] a;
> if (condition) {
>    Array!(int) b;
>    a = b.all;
> }
> writeln(a);
> 
> This is a misuse of the array in that a range crawling on its back has
> survived the array itself. What should happen now? Looking at other
> languages:
> 
> 1) All Java objects are unowned, meaning the issue does not appear in
> the first place, which is an advantage. The disadvantage is that scarce
> resources must be carefully managed by hand in client code.
> 
> 2) C++ makes the behavior undefined because it destroys data AND
> recycles memory as soon as the array goes out of scope. Mayhem ensues.
> 
> We'd like:
> 
> 1.5) Allow object ownership but also make the behavior of incorrect code
> well-defined so it can be reasoned about, reproduced, and debugged.
> 
> That's why I think an Array going out of scope should invoke destructors
> for its data, and then obliterate contents with ElementType.init. That
> way, an Array!(File) will properly close all files AND put them in a
> "closed" state. At the same time, the memory associated with the array
> will NOT be deallocated, so a range surviving the array will never crash
> unrelated code, but instead will see closed files all over.
> 

I don't think this is a good thing, for reasons similar to the Error/Exception flaw - specifically, code that works in debug mode might end up failing in release mode.

To explain what I mean by Error/Exception flaw, consider the case of an array out of bounds error, wrapped carelessly in a try .. catch (Exception) block.

This would work fine in debug mode, and presumably retry the operation until it succeeded.

In release mode, however, the above would crash.

This is clearly undesirable, and arises directly from the fact that Error is derived from Exception, not the other way around or completely separate (as it clearly should be).

After all, an Error ![is] an Exception, since Exceptions are clearly defined as recoverable errors, and the set of unrecoverable errors is obviously not a subset of the recoverable ones.

This leads to my actual point: I suggest an extension of .init: the .fail state, indicating data that should not be accessed.

Any standard library function that encounters data that is intentionally in the .fail state should throw an Error.

For instance, the .fail state for strings could be a deliberately invalid UTF8 sequence.

When this state could reasonably come up in normal operations, it is recommended to use values that will readily be visible in a debugger, such as the classical 0xDEADBEEF.

This is imnsho superior to using .init to fill this memory, which doesn't tell the debugging programmer much about what exactly happened, and furthermore, might cause the program to treat "invalid" memory the same as "fresh" memory, if only by accident.

 --downs


More information about the Digitalmars-d-announce mailing list