Understanding RefCounted
Steven Schveighoffer
schveiguy at gmail.com
Thu May 13 00:53:50 UTC 2021
On 5/12/21 1:16 PM, JG wrote:
> On Wednesday, 12 May 2021 at 13:38:10 UTC, Steven Schveighoffer wrote:
>> On 5/12/21 3:28 AM, JG wrote:
>>> Reading the documentation on RefCounted I get the impression that the
>>> following can lead to memory errors. Could someone explain exactly
>>> how that could happen? I suppose that problem would be the call
>>> something to do with front?
>>>
>>>
>>> ```
>>> private struct RefCountedRangeReturnType(R)
>>> {
>>> import std.typecons : RefCounted;
>>> private RefCounted!R r;
>>> auto empty() { return r.refCountedPayload.empty; }
>>> auto front() { return r.refCountedPayload.front; }
>>> void popFront() { r.refCountedPayload.popFront; }
>>> auto save() { return
>>> typeof(this)(RefCounted!R(r.refCountedPayload.save)); }
>>> }
>>>
>>> auto refCountedRange(R)(R r)
>>> {
>>> import std.typecons : RefCounted;
>>> return RefCountedRangeReturnType!R(RefCounted!R(r));
>>> }
>>> ```
>>
>> You don't need to access refCountedPayload. RefCounted is supposed to
>> be like a transparent reference type, and should forward all calls to
>> the referenced item.
>>
>> I don't see how you will get memory errors from your code. Maybe you
>> can elaborate why you think that is?
>>
>
> To be honest I can't see the problem. But the following from the
> documentation made me wonder if I was doing something that could lead to
> memory problems:
>
> "RefCounted is unsafe and should be used with care. No references to the
> payload should be escaped outside the RefCounted object."
>
> In particular I wondered if in some special case holding a reference to
> front might cause a problem, but perhaps that is incorrect.
>
>
Ah, ok. So reference counting provides a single thing you can point at
and pass around without worrying about memory cleanup. But only as long
as you refer to it strictly through a RefCounted struct. If you keep a
pointer to something in the payload that isn't wrapped in a RefCounted
struct (and specifically the original RefCounted struct), then it's
possible the RefCounted struct will free the memory while you still hold
a reference.
You are returning from front by value, so there shouldn't be a problem
with lifetime issues. However, there are possible exceptions, but they
would be really rare.
As an example of something that would be a bad idea:
```d
struct S
{
int x;
}
int *bad;
{
auto rc = S(1).refCounted;
bad = &rc.x; // escape a reference to the payload
} // here, the scope closes and rc is freed
*bad = 5; // leaving a dangling pointer that can be used
```
-Steve
More information about the Digitalmars-d-learn
mailing list