• Forum
  • Lounge
  • Languages with Deterministic Destructors

 
Languages with Deterministic Destructors

I always have found reliable scope based destruction to be the best thing in C++ by far. It still amazes me all of the other major languages I see seem to solve this problem with GC. If you think GC solves the problem I would say you don't understand the point of destructors. They are a way to handle releasing handles at exact times (file handles, networking, thread guards, etc). Handling memory is just a nice bonus and is mostly handled by smart pointers anyway so don't worry about it.

What other languages handle this like C++? Java doesn't, C# doesn't, Python doesn't. D...does but not really, it's harder from the look of it.

I'm guessing asking about GC here would get the kind of answers I expect, but I'm still interested to hear any opinions.
Rust apparently calls the special "Drop" function when a variable goes out of scope: https://doc.rust-lang.org/book/drop.html Its proponents even call that "RAII"
Last edited on
Interesting, I thought of Rust right after I posted this but I haven't learnt much about it so didn't know. I do see a lot of people complaining about having to use "#[unsafe_destructor]" with it so will go read up on that.

Always looking for more suggestions.
Ada has the notion of "controlled types", with support for C++ like destructor semantics.
http://www.adahome.com/rm95/rm9x-07-06-01.html
James2250: I completely agree with you. I've been working on a backup utility in C# for the past few weeks, and I'm growing pretty sick of the uncertainty of whether I implemented the Dispose()s correctly, or whether I forgot about a using somewhere. This is a serious issue in backup software, which will deals primarily with files. As soon as I solve the serialization problem, I'm porting the code to C++.
Lately I've been juggling with the idea of designing a language with reference counting, reference escape analysis, semi-automatic release of cycles, and deterministic destructors. I posted about it some time ago: http://www.cplusplus.com/forum/lounge/141818/
Nim's feature list looks very interesting, but I haven't had the time to really look at it. I only wish it had ML-like type inference (from what I remember it has C++-like TI) and had an embeddable implementation.
Last edited on
I do find it odd that one cannot develop a language that works well with both a GC and a non-GC allocator.

I used to be a proponent of D because it can do this. You can use malloc instead of the default allocator and it provides facilities for turning raw memory into proper D types.

The problem is it murders the standard library. If you're going to reimplement those parts, like some games and large applications do, it's not that big of a deal. If you have a small app intended to be fast and the GC is giving appalling performance issues, you're completely screwed. D's standard library is closer to Java in this regard. It looks nothing like it would in C++. It can also be hard to determine how the GC is going to react at certain times. It's pretty bad... so bad that I no longer use D because of it.

D has direct support for RAII and it's close to how it looks in C++: http://dlang.org/class.html#destructors

A D struct is a POD so there is no explicit destructor for a struct.
(Sighhh internet....will type this again! Should learn to copy things to notepad first)

@JLBorges: Glad to see C++ isn't quite as alone with RAII as I thought.

@helios: I know that pain. I can barely even use C# these days because of the lack of RAII, it just feels wrong. It's a shame because I think C# can actually be a very powerful language. Interesting to hear about your design ideas for a language, let me know if that ever goes anywhere -- will have to check out Nim too.

@NoXzema: From everything I have read D only has scope based destruction on structs. If you want to use a destructor on a class you either have to wait for the GC, or call scope/delete on the object manually which isn't any better than what C# does. I don't want the client to have to type anything to make RAII work. Am I wrong here?

Have read several articles recently stating that "GC is the best thing ever and gets rid of all of the problems C has with destructors and memory!!!!" Seems like a sad joke, I must be behind the times or something.
For scope-based objects in D, it acts like C++. For heap-based objects, you can call destroy ( http://dlang.org/phobos/object.html#.destroy ) and you then let the GC take care of the rest or free() if you used malloc.
Destroy still needs to be controlled by the client every time though correct? So not true RAII.
Here is my problem with D.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import std.stdio;

struct A
{
	~this() { writeln("Bye!");} 
}

class B
{
	~this() { writeln("Bye!!");} 
}

void Func()
{
       A a;    // Will call destructor as soon as it leaves scope with no work from client  
               // no  inheritance though

       B b = new B() ;   // Up to GC :(      (and has to be constructed with new I believe?)  
}

void main()
{
 	Func();
}


In order to have RAII with classes like C++ it seems you have to do this.

1
2
3
4
5
6
7
8
9
10
scope class B    // Force client to put scope 
{
   ~this() { writeln("Bye!!");} 
}

void Func()
{
      scope B b = new B();        // Yep, works now, no GC.  Annoying to have to put scope though.  
}


Would love to hear if I am wrong, because it seems more work than it should be.
Last edited on
RAII is about resource acquisition during initialization, which implies the ability to fail in a constructor, and, for a language that supports object composition, the ability to roll back all bases and members.
Deterministic destructors are only a part of what makes RAII happen.
Very true, I should stop using them interchangeably. More lazy typing than anything else I think.

I did just mean to focus on deterministic destructors though.
(We can all agree RAII is a terrible acronym though right?)
Question: What's the behavior if the user forgets the "scope" on line 8?
* Program is rejected.
* Program is generated with a resource leak.
* Correct program is generated.
Using Ideone gdc 5.1. Removing scope keyword on line 8.

prog.d:10:9: error: variable prog.Func.b reference to scope class must be scope


Which I actually like (not as much as how C++ does it but whatever), at least the user can't forget like you can in C#/Java etc. It seems D wants you to use structs in this case though and I suppose you don't actually need deterministic destructors with inheritance that often..I guess....still seems odd to me.

I didn't know D had forced scope classes before today though, so I'm slightly happier with it. NoXzema if you use D a lot I would like to hear what you have to say about this kind of usage too.
Last edited on
Nah, I can't use D. I find myself recreating everything and paranoid about the unpredictable GC. D as a language was interesting but my view point of ideal implementation is different from the rest of the D community's.

I know basics at most. The D forums are pretty open to discussion though.
I've just been designing a scope-based language in my free time because of how ridiculous it is that there are so few languages with deterministic destructors. I should have the first compiler ready in a decade or so at this rate.
Last edited on
I look forward to it!

You know where I will be if you ever finish it. If you could convince Microsoft and every other company to start loving everything about RAII that would be great too.
So I just looked at Rust, and it's really awesome...except, classes/inheritance are not a thing and it would be a bad idea to try to recreate them. I wouldn't want to use Rust to make a game, but I'd definitely use it if I ever had to do systems programming.

Rust definitely has RAII - in fact variable scope is the central aspect of the language, as the compiler does all sorts of checking to enforce guarantees about ownership and scope at compile time. There's also no GC that I can see. It even has a Box type which is basically equivalent to std::unique_ptr. So, if you just hate C++ for some reason, Rust is the next best thing.
except, classes/inheritance are not a thing and it would be a bad idea to try to recreate them

Shows how stuck in the OOP mindset I am. I looked at Rust quickly and my first thoughts were to create some structs / create some traits they all share / create a vec<Box<Trait>> container to handle it all (Not sure how accepted in Rust this is). Probably doesn't help I think of games when I look at programming languages.

Maybe should find a fun project to learn Rust from..
Last edited on
James2250 wrote:
Probably doesn't help I think of games when I look at programming languages.
This.
Topic archived. No new replies allowed.