Thread overview | |||||||
---|---|---|---|---|---|---|---|
|
September 22, 2017 Antipattern in core.memory.GC.addRange? | ||||
---|---|---|---|---|
| ||||
GC.addRange has this signature: static nothrow @nogc void addRange(in void* p, size_t sz, const TypeInfo ti = null); I see a large problem with this. Let's say you malloc an array of struct pointers: struct Foo { ... } import core.stdc.stdlib; auto ptrs = (cast(Foo *)malloc(Foo.sizeof * 10))[0 .. 10]; Now, you want to store GC pointers in that block, you need to add the range to the GC: GC.addRange(ptrs.ptr, ptrs.length); See the problem? Why would addRange work this way, when D has such a better mechanism for this? Can we fix it? -Steve |
September 23, 2017 Re: Antipattern in core.memory.GC.addRange? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Friday, 22 September 2017 at 21:29:10 UTC, Steven Schveighoffer wrote:
> GC.addRange has this signature:
>
> static nothrow @nogc void addRange(in void* p, size_t sz, const TypeInfo ti = null);
>
> I see a large problem with this. Let's say you malloc an array of struct pointers:
>
> struct Foo { ... }
>
> import core.stdc.stdlib;
> auto ptrs = (cast(Foo *)malloc(Foo.sizeof * 10))[0 .. 10];
>
> Now, you want to store GC pointers in that block, you need to add the range to the GC:
>
> GC.addRange(ptrs.ptr, ptrs.length);
>
> See the problem?
Yes, you forgot to multiply by Foo.sizeof.
Using the pattern from the example in the documentation,
the code would be:
size_t bytes = Foo.sizeof * 10;
auto ptrs = (cast(Foo *)malloc(bytes))[0 .. 10];
GC.addRange(ptrs.ptr, bytes);
|
September 23, 2017 Re: Antipattern in core.memory.GC.addRange? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Friday, 22 September 2017 at 21:29:10 UTC, Steven Schveighoffer wrote:
> GC.addRange has this signature:
>
> static nothrow @nogc void addRange(in void* p, size_t sz, const TypeInfo ti = null);
>
> I see a large problem with this. Let's say you malloc an array of struct pointers:
>
> struct Foo { ... }
>
> import core.stdc.stdlib;
> auto ptrs = (cast(Foo *)malloc(Foo.sizeof * 10))[0 .. 10];
>
> Now, you want to store GC pointers in that block, you need to add the range to the GC:
>
> GC.addRange(ptrs.ptr, ptrs.length);
>
> See the problem? Why would addRange work this way, when D has such a better mechanism for this? Can we fix it?
>
> -Steve
How about adding a template wrapper function, along the lines of:
static void addRange(T)(const T[] arr)
{
addRange(arr.ptr, T.sizeof * arr.length, typeid(T));
}
To core.memory.GC?
|
September 23, 2017 Re: Antipattern in core.memory.GC.addRange? | ||||
---|---|---|---|---|
| ||||
Posted in reply to safety0ff | On 9/23/17 1:30 AM, safety0ff wrote:
> On Friday, 22 September 2017 at 21:29:10 UTC, Steven Schveighoffer wrote:
>> GC.addRange has this signature:
>>
>> static nothrow @nogc void addRange(in void* p, size_t sz, const TypeInfo ti = null);
>>
>> I see a large problem with this. Let's say you malloc an array of struct pointers:
>>
>> struct Foo { ... }
>>
>> import core.stdc.stdlib;
>> auto ptrs = (cast(Foo *)malloc(Foo.sizeof * 10))[0 .. 10];
>>
>> Now, you want to store GC pointers in that block, you need to add the range to the GC:
>>
>> GC.addRange(ptrs.ptr, ptrs.length);
>>
>> See the problem?
>
> Yes, you forgot to multiply by Foo.sizeof.
>
> Using the pattern from the example in the documentation,
> the code would be:
>
> size_t bytes = Foo.sizeof * 10;
> auto ptrs = (cast(Foo *)malloc(bytes))[0 .. 10];
> GC.addRange(ptrs.ptr, bytes);
>
Right, the problem is that the API accepts this without error, because of the implicit cast to void *.
The simple rule should be that if we can prevent something obviously wrong from compiling, we should do so.
-Steve
|
September 23, 2017 Re: Antipattern in core.memory.GC.addRange? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Petar Kirov [ZombineDev] | On 9/23/17 1:55 AM, Petar Kirov [ZombineDev] wrote:
>
> How about adding a template wrapper function, along the lines of:
> static void addRange(T)(const T[] arr)
> {
> addRange(arr.ptr, T.sizeof * arr.length, typeid(T));
> }
>
>
> To core.memory.GC?
It sounds good. But will it be accepted?
Note, the true implementation should use integer overflow to reject invalid arrays.
-Steve
|
Copyright © 1999-2021 by the D Language Foundation