On Friday, 8 April 2022 at 04:31:45 UTC, Elvis Zhou wrote:
>B b;
init(&b);
structs ~= cast(A*)&b;
//Error: copying cast(A*)\& b
into allocated memory escapes a reference to local variable b
Maybe it should be cast(A*) \&b.a
?
Thread overview | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
April 08, 2022 How to implement this? | ||||
---|---|---|---|---|
| ||||
struct A {} struct B { A a; } struct C { A a; } A*[] structs; B b; init(&b); structs ~= cast(A*)&b; //Error: copying `cast(A*)& b` into allocated memory escapes a reference to local variable `b` C c; init(&c); structs ~= cast(A*)&c; //Error: copying `cast(A*)& c` into allocated memory escapes a reference to local variable `c` batch_process(structs); |
April 08, 2022 Re: How to implement this? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Elvis Zhou | On Friday, 8 April 2022 at 04:31:45 UTC, Elvis Zhou wrote: >B b; Maybe it should be |
April 08, 2022 Re: How to implement this? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Era Scarecrow | On Friday, 8 April 2022 at 04:54:35 UTC, Era Scarecrow wrote: >Maybe it should be Confusing HTML entities bit on here. Probably just ignore it. Maybe you are doing it backwards. What if you had
then in the init append a new item to A's array list, before doing:
Alternately, add a static list and have the batch function access both lists?
then reference the item by list[a_index] or something similar. |
April 07, 2022 Re: How to implement this? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Elvis Zhou | On 4/7/22 21:31, Elvis Zhou wrote: > > struct A {} > struct B { A a; } > struct C { A a; } > > A*[] structs; > > B b; > init(&b); > structs ~= cast(A*)&b; > //Error: copying `cast(A*)& b` into allocated memory escapes a reference > to local variable `b` If that really is the case, you want to place the objects on memory that will not go away. Dynamic arrays provide "memory" that is owned by the GC. The following program emplaces alternating Bs and Cs into a buffer and then batch_process'es them: struct A { int i; } struct B { A a; } struct C { A a; } A*[] structs; void append(T, Args...)(ref ubyte[] structs, Args args) { import std.conv : emplace; structs.length += sizeWithPadding!T; auto where = cast(T*)(&structs[$ - sizeWithPadding!T]); emplace(where, args); } void main() { ubyte[] structs; foreach (i; 0 .. 10) { if (i % 2) { structs.append!B(A(i)); } else { structs.append!C(A(i)); } } batch_process(structs); } auto process(T)(const(ubyte)[] structs) { import std.stdio : writeln; writeln(*cast(T*)structs.ptr); return structs[sizeWithPadding!T..$]; } void batch_process(const(ubyte)[] structs) { import std.range : empty; for (size_t i = 0; !structs.empty; i++) { if (i % 2) { structs = structs.process!B(); } else { structs = structs.process!C(); } } } T * nextAlignedAddress(T)(T * candidateAddr) { import std.traits; static if (is (T == class)) { const alignment = classInstanceAlignment!T; } else { const alignment = T.alignof; } const result = (cast(size_t)candidateAddr + alignment - 1) / alignment * alignment; return cast(T*)result; } void * nextAlignedAddress(T)(void * candidateAddr) { return nextAlignedAddress(cast(T*)candidateAddr); } size_t sizeWithPadding(T)() { static if (is (T == class)) { const candidateAddr = __traits(classInstanceSize, T); } else { const candidateAddr = T.sizeof; } return cast(size_t)nextAlignedAddress(cast(T*)candidateAddr); } I copied nextAlignedAddress() and sizeWithPadding() functions from this chapter: http://ddili.org/ders/d.en/memory.html Everything I did in the program above is explained there. Ali |
April 08, 2022 Re: How to implement this? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Elvis Zhou | On Friday, 8 April 2022 at 04:31:45 UTC, Elvis Zhou wrote:
>
> struct A {}
> struct B { A a; }
> struct C { A a; }
>
> A*[] structs;
>
> B b;
> init(&b);
> structs ~= cast(A*)&b;
> //Error: copying `cast(A*)& b` into allocated memory escapes a reference to local variable `b`
>
> C c;
> init(&c);
> structs ~= cast(A*)&c;
> //Error: copying `cast(A*)& c` into allocated memory escapes a reference to local variable `c`
>
> batch_process(structs);
I know where the issue comes from, dynamic array is GCed and save the reference of a local variable in GCed memory is not allowed, but here structs is assumed to not escape, it can be simply achieved by using a fixed-size array instead, ie A*[32] structs; int i = 0; structs[i++] = cast(A*)&b; However I wonder if there be a stack allocated array with max capacity limits, which can be concated like with normal dynamic one.
|
April 08, 2022 Re: How to implement this? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Elvis Zhou | On Friday, 8 April 2022 at 05:46:56 UTC, Elvis Zhou wrote: > On Friday, 8 April 2022 at 04:31:45 UTC, Elvis Zhou wrote: >> [...] > > I know where the issue comes from, dynamic array is GCed and save the reference of a local variable in GCed memory is not allowed, but here structs is assumed to not escape, it can be simply achieved by using a fixed-size array instead, ie A*[32] structs; int i = 0; structs[i++] = cast(A*)&b; However I wonder if there be a stack allocated array with max capacity limits, which can be concated like with normal dynamic one. like, assumeNoEscapeOrWhatever!DynamicArray structs; structs ~= cast(A*)&b; is it possible? |
April 08, 2022 Re: How to implement this? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Elvis Zhou | On Friday, 8 April 2022 at 05:53:03 UTC, Elvis Zhou wrote:
> assumeNoEscapeOrWhatever!DynamicArray structs;
> structs ~= cast(A*)&b;
>
> is it possible?
That's what `@trusted` is for. And that's also why it should be used with care, and on the smallest code possible.
```d
struct A {}
struct B { A a; }
struct C { A a; }
void main()
{
A*[] structs;
B b;
C c;
() @trusted {
structs ~= cast(A*)&b;
structs ~= cast(A*)&c;
} ();
}
```
|
April 08, 2022 Re: How to implement this? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Stanislav Blinov | On Friday, 8 April 2022 at 09:08:07 UTC, Stanislav Blinov wrote:
> On Friday, 8 April 2022 at 05:53:03 UTC, Elvis Zhou wrote:
>
>> assumeNoEscapeOrWhatever!DynamicArray structs;
>> structs ~= cast(A*)&b;
>>
>> is it possible?
>
> That's what `@trusted` is for. And that's also why it should be used with care, and on the smallest code possible.
>
> ```d
> struct A {}
> struct B { A a; }
> struct C { A a; }
>
> void main()
> {
> A*[] structs;
>
> B b;
> C c;
>
> () @trusted {
> structs ~= cast(A*)&b;
> structs ~= cast(A*)&c;
> } ();
> }
> ```
Thank you, this is exactly what I'm looking for!
But why this doesn't work?
void func() @trusted
{
A*[] structs;
B b;
structs ~= cast(A*)&b; // still error
}
|