Advice wanted on garbage collection of sockets for c++ programmer using D

Steven Schveighoffer via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue Jun 27 06:11:10 PDT 2017


On 6/27/17 8:29 AM, Guillaume Piolat wrote:
> On Tuesday, 27 June 2017 at 09:54:19 UTC, John Burton wrote:
>> Am I doing this right with GC? In C++ I'd ensure that the Socket class 
>> had a destructor that closed the socket and I'd also assume that once 
>> it went out of scope there was no memory left allocated. In D am I 
>> right to assume I need to manually close the socket but there is no 
>> need to worry about the memory?
> 
> Yes.
> You can also call a destructor manually with destroy(obj);
> This avoids having a forest of 'close' methods, who are duplicates of 
> the destructor in spirit, and let's you use destructors like you are 
> accustomed in C++.
> 
> Generally, it is dangerous to let the GC handle resource release:
> https://p0nce.github.io/d-idioms/#The-trouble-with-class-destructors

This is the best to read, it's very tricky for people coming from other 
languages I think to understand the rules around the GC destructor.

I think you have gotten sound advice from many people, but I wanted to 
chime in as someone who used the GC to clean up sockets and file handles 
in a long-running program. Even with all these warnings, it does seem to 
work. My advice is to close the socket in the destructor if still valid, 
and then manually close it also. This way you don't leak resources if 
you miss a close call.

The fundamental problem with closing sockets and other resources with 
the GC is that the resource management issues and rules for memory are 
vastly different than those of other resources. The OS can give you vast 
sums of memory, but will likely limit your ability to keep sockets open. 
It also keeps the other end potentially locked up. If you try to 
allocate a new socket and run out of sockets, there is no "socket 
collection cycle". This is why closing manually is advised.

But I would use a close method, and not destroy(obj). The reason is 
because often times, you have wrapper types around your socket type, and 
just one extra level of indirection means the destructor cannot be used 
to clean up the socket (you are not allowed to access GC-allocated 
resources in a destructor).

Using std.typecons.RefCounted also can help to ensure destruction of a 
socket when it's no longer used. But like I said, it's not always 
possible to use a destructor of a higher level object to clean up a socket.

-Steve


More information about the Digitalmars-d-learn mailing list