digitalmars.D - Antipattern in core.memory.GC.addRange?
- Steven Schveighoffer (14/14) Sep 22 2017 GC.addRange has this signature:
- safety0ff (8/20) Sep 22 2017 Yes, you forgot to multiply by Foo.sizeof.
- Steven Schveighoffer (6/36) Sep 23 2017 Right, the problem is that the API accepts this without error, because
- Petar Kirov [ZombineDev] (8/22) Sep 22 2017 How about adding a template wrapper function, along the lines of:
- Steven Schveighoffer (5/14) Sep 23 2017 It sounds good. But will it be accepted?
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
Sep 22 2017
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);
Sep 22 2017
On 9/23/17 1:30 AM, safety0ff wrote:On Friday, 22 September 2017 at 21:29:10 UTC, Steven Schveighoffer wrote: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. -SteveGC.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);
Sep 23 2017
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?
Sep 22 2017
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
Sep 23 2017









Steven Schveighoffer <schveiguy yahoo.com> 