digitalmars.D.learn - Partially initialized structs?
- Arredondo (37/37) Feb 25 Is it possible to declare a partially initialized struct?
- Hipreme (22/59) Feb 26 I highly recommend you don't do that.
- Arredondo (9/22) Feb 26 Thank you for this Hipreme. I do have a question though, wouldn't
- bkoie (3/11) Feb 26 stuff like this is not even necessary if you dont need it now
- Salih Dincer (67/69) Feb 26 It's not that simple. I found the following code very
- bkoie (4/10) Feb 26 code doing a bunch of undefined runtime magic
- Salih Dincer (64/74) Feb 26 I hate CPP. If we had done something similar by relying on him,
- user1234 (243/312) Feb 26 after exit valgrind is very happy with that code.
- Arredondo (4/6) Feb 26 I'm not sure that would work for me with the way I'm iteratively
Is it possible to declare a partially initialized struct? I would have thought that doing it like this would work: ``` struct S { int[100] a = void; int b = 0; } ``` But when I declare a variable of type `S`, the array `a` is initialized, so it seems that the `= void` is not playing any role here. Of course `S s = void;` works for `a`, but then `b` is not initialized. I tried doing: ``` struct S { disable this (); auto this(int b) { this.b = b; a = void; } int[100] a; int b = 0; } ``` But that doesn't even compile. I'm currently settling for something like: ``` auto placeS(string name)() => iq{ S $(name) = void; $(name).b = 0; }.text; ``` and then declare with `mixin(placeS!"s");`. Is there a better way? Cheers! Arredondo.
Feb 25
On Wednesday, 26 February 2025 at 03:47:32 UTC, Arredondo wrote:Is it possible to declare a partially initialized struct? I would have thought that doing it like this would work: ``` struct S { int[100] a = void; int b = 0; } ``` But when I declare a variable of type `S`, the array `a` is initialized, so it seems that the `= void` is not playing any role here. Of course `S s = void;` works for `a`, but then `b` is not initialized. I tried doing: ``` struct S { disable this (); auto this(int b) { this.b = b; a = void; } int[100] a; int b = 0; } ``` But that doesn't even compile. I'm currently settling for something like: ``` auto placeS(string name)() => iq{ S $(name) = void; $(name).b = 0; }.text; ``` and then declare with `mixin(placeS!"s");`. Is there a better way? Cheers! Arredondo.I highly recommend you don't do that. I've been using D for more than 5 years and that led me to a bug which took me some time to solve that quite recently. The proper way to to do it is creating an implementation of a void init instead: ```d struct S { int[100] a; int b = 0; static S defaultInit(int b) { S s = void; s.b = b; return s; } } ``` Having `void` initialization on fields would be really unsafe and could break your code at any moment and that would be really hard to identify. With that you'll be able at least to fix that issue.
Feb 26
On Wednesday, 26 February 2025 at 10:19:17 UTC, Hipreme wrote:```d struct S { int[100] a; int b = 0; static S defaultInit(int b) { S s = void; s.b = b; return s; } } ```Thank you for this Hipreme. I do have a question though, wouldn't this create two copies of S? one at construction and then another at the call site after defaultInit returns? Regarding safety, I'm well aware I'm playing with fire here. For now I'm just experimenting to see if something like this is even worth it performance-wise. Cheers! Arredondo.
Feb 26
On Wednesday, 26 February 2025 at 23:47:41 UTC, Arredondo wrote:On Wednesday, 26 February 2025 at 10:19:17 UTC, Hipreme wrote:Yes, that is definitely worth performance wise. Specially if you wish to start using an array of `S`, this could be a huge toll. And no, it won't create 2 copies. D has a thing called Return Value Optimization. Since that local variable is returned, it has no need to copy it.```d struct S { int[100] a; int b = 0; static S defaultInit(int b) { S s = void; s.b = b; return s; } } ```Thank you for this Hipreme. I do have a question though, wouldn't this create two copies of S? one at construction and then another at the call site after defaultInit returns? Regarding safety, I'm well aware I'm playing with fire here. For now I'm just experimenting to see if something like this is even worth it performance-wise. Cheers! Arredondo.
Feb 26
On Thursday, 27 February 2025 at 01:22:07 UTC, Hipreme wrote:And no, it won't create 2 copies. D has a thing called Return Value Optimization. Since that local variable is returned, it has no need to copy it.That's great to know. Thank you!
Feb 26
On Thursday, 27 February 2025 at 02:09:29 UTC, Arredondo wrote:On Thursday, 27 February 2025 at 01:22:07 UTC, Hipreme wrote:```d template Model(T, T n = 100) // where n: length with Type of T { auto voidStackArr(inout bool _void = true) { T[n] arr = void; assert(!_void); arr = 0; return arr; } } alias voidStackArrInt = Model!int; void main() { import std.stdio: writeln; // err we are reading garb values auto arr = voidStackArrInt.voidStackArr; arr.writeln; // ok auto arr2 = voidStackArrInt.voidStackArr(false); arr2.writeln; } ``` and we're back to c++ u guys should really stop doing things like thisAnd no, it won't create 2 copies. D has a thing called Return Value Optimization. Since that local variable is returned, it has no need to copy it.That's great to know. Thank you!
Feb 26
On Thursday, 27 February 2025 at 06:15:38 UTC, bkoie wrote:template Model(T, T n = 100) // where n: length with Type of Tspoiler alert: there is fun to be had here; your going to want to clear your sleep sch, stock up on caffine, digging into this syntax is a wild ride of some of the best compiler bugs d can offer 10/10
Feb 26
On Wednesday, 26 February 2025 at 03:47:32 UTC, Arredondo wrote:Is it possible to declare a partially initialized struct? I would have thought that doing it like this would work: ``` struct S { int[100] a = void; int b = 0; } ```stuff like this is not even necessary if you dont need it now dont delcare an easy workaround is use some copy dictionary.
Feb 26
On Wednesday, 26 February 2025 at 15:11:47 UTC, bkoie wrote:stuff like this is not even necessary if you dont need it now dont delcare an easy workaround is use some copy dictionary.It's not that simple. I found the following code very sympathetic. You can use the same method for structures that contain dynamic arrays and can be customized as needed... ```d alias MSS(T) = My_Static_Struct!T; struct My_Static_Struct(Type) { Type id = 0; Type[8] arr; alias T = typeof(this); disable this (); static init(Type id) { T that = void; that.id = id; return that; } } alias MDS(T) = My_Dynamic_Struct!T; struct My_Dynamic_Struct(Type) { Type id; Type[] arr; alias T = typeof(this); disable this (); static init(Type id, size_t length) { alias R = Type[]; import std.range : uninitializedArray; T that = void; that.id = id; that.arr = length.uninitializedArray!R; return that; } } import std.stdio; void main() { alias T = ubyte; MSS!T[] m1; with(MSS!T) { m1 = [ init(41), init(42) ]; } m1.writefln!"%-(%s\n%)"; MDS!T[] m2; with(MDS!T) { m2 = [ init(41, 4), init(42, 8) ]; } m2.writefln!"%-(%s\n%)"; } /* PRINTS: My_Static_Struct!ubyte(41, [0, 0, 0, 0, 0, 0, 0, 0]) My_Static_Struct!ubyte(42, [0, 0, 0, 0, 0, 0, 0, 0]) My_Dynamic_Struct!ubyte(41, [16, 32, 216, 47]) My_Dynamic_Struct!ubyte(42, [32, 32, 216, 47, 100, 127, 0, 0]) */ ``` SDB 79
Feb 26
On Wednesday, 26 February 2025 at 16:38:20 UTC, Salih Dincer wrote:My_Static_Struct!ubyte(41, [0, 0, 0, 0, 0, 0, 0, 0]) My_Static_Struct!ubyte(42, [0, 0, 0, 0, 0, 0, 0, 0]) My_Dynamic_Struct!ubyte(41, [16, 32, 216, 47]) My_Dynamic_Struct!ubyte(42, [32, 32, 216, 47, 100, 127, 0, 0]) */ ```code doing a bunch of undefined runtime magic if you think this is valid then you will enjoy c++.
Feb 26
On Wednesday, 26 February 2025 at 19:34:24 UTC, bkoie wrote:On Wednesday, 26 February 2025 at 16:38:20 UTC, Salih Dincer wrote:I hate CPP. If we had done something similar by relying on him, we would probably have struggled too hard. Cheers with :D AI (DeepSeek) generated the following code that did not work in response: ```CPP #include <array> #include <vector> #include <memory> #include <iostream> template <typename Type> struct My_Static_Struct { Type id; std::array<Type, 8> arr; My_Static_Struct() = delete; static My_Static_Struct init(Type id_val) { return {id_val, {}}; } }; template <typename Type> struct My_Dynamic_Struct { Type id; std::unique_ptr<Type[]> arr; size_t arr_length; My_Dynamic_Struct() = delete; static My_Dynamic_Struct init(Type id_val, size_t length) { return {id_val, std::unique_ptr<Type[]>(new Type[length]), length}; } }; int main() { using T = unsigned char; // My_Static_Struct kullanımı using MSS = My_Static_Struct<T>; std::vector<MSS> m1 = { MSS::init(41), MSS::init(42) }; for (const auto& elem : m1) { std::cout << "MSS id: " << static_cast<int>(elem.id) << " | arr: "; for (auto val : elem.arr) { std::cout << static_cast<int>(val) << " "; } std::cout << std::endl; } // My_Dynamic_Struct kullanımı using MDS = My_Dynamic_Struct<T>; std::vector<MDS> m2 = { MDS::init(41, 4), MDS::init(42, 8) }; for (const auto& elem : m2) { std::cout << "MDS id: " << static_cast<int>(elem.id) << " | arr: "; for (size_t i = 0; i < elem.arr_length; ++i) { std::cout << static_cast<int>(elem.arr[i]) << " "; } std::cout << std::endl; } return 0; } ``` SDB 79My_Static_Struct!ubyte(41, [0, 0, 0, 0, 0, 0, 0, 0]) My_Static_Struct!ubyte(42, [0, 0, 0, 0, 0, 0, 0, 0]) My_Dynamic_Struct!ubyte(41, [16, 32, 216, 47]) My_Dynamic_Struct!ubyte(42, [32, 32, 216, 47, 100, 127, 0, 0]) */ ```code doing a bunch of undefined runtime magic if you think this is valid then you will enjoy c++.
Feb 26
On Wednesday, 26 February 2025 at 16:38:20 UTC, Salih Dincer wrote:On Wednesday, 26 February 2025 at 15:11:47 UTC, bkoie wrote:after exit valgrind is very happy with that code. Simple main: ``` =24625== Memcheck, a memory error detector ==24625== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. ==24625== Using Valgrind-3.22.0 and LibVEX; rerun with -h for copyright info ==24625== Command: /tmp/temp_7F2438E29F90 ==24625== ==24625== ==24625== HEAP SUMMARY: ==24625== in use at exit: 72 bytes in 2 blocks ==24625== total heap usage: 101 allocs, 99 frees, 9,040 bytes allocated ==24625== ==24625== LEAK SUMMARY: ==24625== definitely lost: 0 bytes in 0 blocks ==24625== indirectly lost: 0 bytes in 0 blocks ==24625== possibly lost: 0 bytes in 0 blocks ==24625== still reachable: 72 bytes in 2 blocks ==24625== suppressed: 0 bytes in 0 blocks ==24625== Rerun with --leak-check=full to see details of leaked memory ==24625== ==24625== For lists of detected and suppressed errors, rerun with: -s ==24625== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) ``` Your program: ``` ==24746== Memcheck, a memory error detector ==24746== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. ==24746== Using Valgrind-3.22.0 and LibVEX; rerun with -h for copyright info ==24746== Command: /tmp/temp_7F2438E29F90 ==24746== ==24746== Conditional jump or move depends on uninitialised value(s) ==24746== at 0x45DC79: std.format.internal.write.formatValueImplUlong!(std.stdio.Fil .LockingTextWriter, char).formatValueImplUlong(ref std.stdio.File.LockingTextWriter, ulong, in bool, scope ref const(std.format.spec.FormatSpec!(char).FormatSpec)) (write.d:193) ==24746== by 0x45DA91: std.format.internal.write.formatValueImpl!(std.stdio.File.LockingTextWriter, ubyte, char).formatValueImpl(ref std.stdio.File.LockingTextWriter, const(ubyte), scope ref const(std.format.spec.FormatSpec!(char).FormatSpec)) (write.d:173) ==24746== by 0x45D95B: std.format.write.formatValue!(std.stdio.File.LockingTextWriter, ubyte, char).formatValue(ref std.stdio.File.LockingTextWriter, ref ubyte, scope ref const(std.format.spec.FormatSpec!(char).FormatSpec)) (write.d:1239) ==24746== by 0x45D8E0: std.format.internal.write.formatElement!(std.stdio.File.LockingTextWriter, ubyte, char).formatElement(ref std.stdio.File.LockingTextWriter, ref ubyte, scope ref const(std.format.spec.FormatSpec!(char).FormatSpec)) (write.d:3218) ==24746== by 0x46047B: std.format.internal.write.formatRange!(std.stdio.File.LockingTextWriter, ubyte[], char).formatRange(ref std.stdio.File.LockingTextWriter, ref ubyte[], scope ref const(std.format.spec.FormatSpec!(char).FormatSpec)) (write.d:1497) ==24746== by 0x4603E4: std.format.internal.write.formatValueImpl!(std.stdio.File.LockingTextWriter, ubyte[], char).formatValueImpl(ref std.stdio.File.LockingTextWriter, ubyte[], scope ref const(std.format.spec.FormatSpec!(char).FormatSpec)) (write.d:1281) ==24746== by 0x4603B9: std.format.internal.write.formatValueImpl!(std.stdio.File.LockingTextWriter, ubyte[8], char).formatValueImpl(ref std.stdio.File.LockingTextWriter, ref ubyte[8], scope ref const(std.format.spec.FormatSpec!(char).FormatSpec)) (write.d:1230) ==24746== by 0x46036F: std.format.write.formatValue!(std.stdio.File.LockingTextWriter, ubyte[8], char).formatValue(ref std.stdio.File.LockingTextWriter, ref ubyte[8], scope ref const(std.format.spec.FormatSpec!(char).FormatSpec)) (write.d:1239) ==24746== by 0x4602F8: std.format.internal.write.formatElement!(std.stdio.File.LockingTextWriter, ubyte[8], char).formatElement(ref std.stdio.File.LockingTextWriter, ref ubyte[8], scope ref const(std.format.spec.FormatSpec!(char).FormatSpec)) (write.d:3218) ==24746== by 0x45D896: std.format.internal.write.formatValueImpl!(std.stdio.File.LockingTextWriter, temp_7F2438E29F90.My_Static_Struct!(ubyte).My_Static_Struct, char).formatValueImpl(ref std.stdio.File.LockingTextWriter, ref temp_7F2438E29F90.My_Static_Struct!(ubyte).My_Static_Struct, scope ref const(std.format.spec.FormatSpec!(char).FormatSpec)) (write.d:2557) ==24746== by 0x45D7F3: std.format.write.formatValue!(std.stdio.File.LockingTextWriter, temp_7F2438E29F90.My_Static_Struct!(ubyte).My_Static_Struct, char).formatValue(ref std.stdio.File.LockingTextWriter, ref temp_7F2438E29F90.My_Static_Struct!(ubyte).My_Static_Struct, scope ref const(std.format.spec.FormatSpec!(char).FormatSpec)) (write.d:1239) ==24746== by 0x45D296: std.format.internal.write.formatRange!(std.stdio.File.LockingTextWriter, temp_7F2438E29F90.My_Static_Struct!(ubyte).My_Static_Struct[], char).formatRange(ref std.stdio.File.LockingTextWriter, ref temp_7F2438E29F90.My_Static_Struct!(ubyte).My_Static_Struct[], scope ref const(std.format.spec.FormatSpec!(char).FormatSpec)) (write.d:1545) ==24746== ==24746== Conditional jump or move depends on uninitialised value(s) ==24746== at 0x49F836C: _IO_new_file_xsputn (fileops.c:1218) ==24746== by 0x49F836C: _IO_file_xsputn GLIBC_2.2.5 (fileops.c:1196) ==24746== by 0x49ED596: fwrite (iofwrite.c:39) ==24746== by 0x45C961: std.stdio.trustedFwrite!(char).trustedFwrite(shared(core.stdc.stdio._IO_FILE)*, const(char[])) (stdio.d:4751) ==24746== by 0x45F4A3: std.stdio.File.LockingTextWriter.put!(char[]).put(scope char[]) (stdio.d:3211) ==24746== by 0x45F45A: std.range.primitives.doPut!(std.stdio.File.LockingTextWriter, char[]).doPut(ref std.stdio.File.LockingTextWriter, ref char[]) (primitives.d:307) ==24746== by 0x45F42C: std.range.primitives.put!(std.stdio.File.LockingTextWriter, char[]).put(ref std.stdio.File.LockingTextWriter, char[]) (primitives.d:410) ==24746== by 0x45F067: std.format.internal.write.writeAligned!(std.stdio.File.LockingTextWriter, char[], char[], immutable(char)[], immutable(char)[], char).writeAligned(ref std.stdio.File.LockingTextWriter, char[], char[], immutable(char)[], immutable(char)[], scope ref const(std.format.spec.FormatSpec!(char).FormatSpec), std.format.internal.write.PrecisionType) (write.d:3464) ==24746== by 0x45E7FE: std.format.internal.write.writeAligned!(std.stdio.File.LockingTextWriter, char[], char[], immutable(char)[], char).writeAligned(ref std.stdio.File.LockingTextWriter, char[], char[], immutable(char)[], scope ref const(std.format.spec.FormatSpec!(char).FormatSpec), bool) (write.d:3316) ==24746== by 0x45E038: std.format.internal.write.formatValueImplUlong!(std.stdio.Fil .LockingTextWriter, char).formatValueImplUlong(ref std.stdio.File.LockingTextWriter, ulong, in bool, scope ref const(std.format.spec.FormatSpec!(char).FormatSpec)) (write.d:224) ==24746== by 0x45DA91: std.format.internal.write.formatValueImpl!(std.stdio.File.LockingTextWriter, ubyte, char).formatValueImpl(ref std.stdio.File.LockingTextWriter, const(ubyte), scope ref const(std.format.spec.FormatSpec!(char).FormatSpec)) (write.d:173) ==24746== by 0x45D95B: std.format.write.formatValue!(std.stdio.File.LockingTextWriter, ubyte, char).formatValue(ref std.stdio.File.LockingTextWriter, ref ubyte, scope ref const(std.format.spec.FormatSpec!(char).FormatSpec)) (write.d:1239) ==24746== by 0x45D8E0: std.format.internal.write.formatElement!(std.stdio.File.LockingTextWriter, ubyte, char).formatElement(ref std.stdio.File.LockingTextWriter, ref ubyte, scope ref const(std.format.spec.FormatSpec!(char).FormatSpec)) (write.d:3218) ==24746== ==24746== Syscall param write(buf) points to uninitialised byte(s) ==24746== at 0x4A70324: write (write.c:26) ==24746== by 0x49F7D2C: _IO_file_write GLIBC_2.2.5 (fileops.c:1180) ==24746== by 0x49F70CF: new_do_write (fileops.c:448) ==24746== by 0x49F8D98: _IO_do_write GLIBC_2.2.5 (fileops.c:425) ==24746== by 0x49F83DD: _IO_new_file_xsputn (fileops.c:1243) ==24746== by 0x49F83DD: _IO_file_xsputn GLIBC_2.2.5 (fileops.c:1196) ==24746== by 0x49ED596: fwrite (iofwrite.c:39) ==24746== by 0x45C961: std.stdio.trustedFwrite!(char).trustedFwrite(shared(core.stdc.stdio._IO_FILE)*, const(char[])) (stdio.d:4751) ==24746== by 0x45C893: std.stdio.File.LockingTextWriter.put!(const(char)[]).put(scope const(char)[]) (stdio.d:3211) ==24746== by 0x45C84A: std.range.primitives.doPut!(std.stdio.File.LockingTextWriter, const(char)[]).doPut(ref std.stdio.File.LockingTextWriter, ref const(char)[]) (primitives.d:307) ==24746== by 0x45C81C: std.range.primitives.put!(std.stdio.File.LockingTextWriter, const(char)[]).put(ref std.stdio.File.LockingTextWriter, const(char)[]) (primitives.d:410) ==24746== by 0x45D3D7: std.format.internal.write.formatRange!(std.stdio.File.LockingTextWriter, temp_7F2438E29F90.My_Static_Struct!(ubyte).My_Static_Struct[], char).formatRange(ref std.stdio.File.LockingTextWriter, ref temp_7F2438E29F90.My_Static_Struct!(ubyte).My_Static_Struct[], scope ref const(std.format.spec.FormatSpec!(char).FormatSpec)) (write.d:1575) ==24746== by 0x45D004: std.format.internal.write.formatValueImpl!(std.stdio.File.LockingTextWriter, temp_7F2438E29F90.My_Static_Struct!(ubyte).My_Static_Struct[], char).formatValueImpl(ref std.stdio.File.LockingTextWriter, temp_7F2438E29F90.My_Static_Struct!(ubyte).My_Static_Struct[], scope ref const(std.format.spec.FormatSpec!(char).FormatSpec)) (write.d:1281) ==24746== Address 0x4b60c5c is 28 bytes inside a block of size 1,024 alloc'd ==24746== at 0x484380F: malloc (vg_replace_malloc.c:442) ==24746== by 0x49EC273: _IO_file_doallocate (filedoalloc.c:101) ==24746== by 0x49F9E9F: _IO_doallocbuf (genops.c:347) ==24746== by 0x49F9E9F: _IO_doallocbuf (genops.c:342) ==24746== by 0x49F9237: _IO_file_overflow GLIBC_2.2.5 (fileops.c:744) ==24746== by 0x49F83DD: _IO_new_file_xsputn (fileops.c:1243) ==24746== by 0x49F83DD: _IO_file_xsputn GLIBC_2.2.5 (fileops.c:1196) ==24746== by 0x49ED596: fwrite (iofwrite.c:39) ==24746== by 0x45C961: std.stdio.trustedFwrite!(char).trustedFwrite(shared(core.stdc.stdio._IO_FILE)*, const(char[])) (stdio.d:4751) ==24746== by 0x45D4DB: std.stdio.File.LockingTextWriter.put!(immutable(char)[]).put(scope immutable(char)[]) (stdio.d:3211) ==24746== by 0x45D492: std.range.primitives.doPut!(std.stdio.File.LockingTextWriter, immutable(char)[]).doPut(ref std.stdio.File.LockingTextWriter, ref immutable(char)[]) (primitives.d:307) ==24746== by 0x45D464: std.range.primitives.put!(std.stdio.File.LockingTextWriter, immutable(char)[]).put(ref std.stdio.File.LockingTextWriter, immutable(char)[]) (primitives.d:410) ==24746== by 0x45D850: std.format.internal.write.formatValueImpl!(std.stdio.File.LockingTextWriter, temp_7F2438E29F90.My_Static_Struct!(ubyte).My_Static_Struct, char).formatValueImpl(ref std.stdio.File.LockingTextWriter, ref temp_7F2438E29F90.My_Static_Struct!(ubyte).My_Static_Struct, scope ref const(std.format.spec.FormatSpec!(char).FormatSpec)) (write.d:2528) ==24746== by 0x45D7F3: std.format.write.formatValue!(std.stdio.File.LockingTextWriter, temp_7F2438E29F90.My_Static_Struct!(ubyte).My_Static_Struct, char).formatValue(ref std.stdio.File.LockingTextWriter, ref temp_7F2438E29F90.My_Static_Struct!(ubyte).My_Static_Struct, scope ref const(std.format.spec.FormatSpec!(char).FormatSpec)) (write.d:1239) ==24746== My_Static_Struct!ubyte(41, [0, 0, 0, 0, 0, 0, 0, 0]) My_Static_Struct!ubyte(42, [0, 0, 0, 0, 0, 0, 0, 0]) My_Dynamic_Struct!ubyte(41, [16, 96, 245, 4]) My_Dynamic_Struct!ubyte(42, [32, 96, 245, 4, 0, 0, 0, 0]) ==24746== Conditional jump or move depends on uninitialised value(s) ==24746== at 0x4A79B7: core.internal.gc.impl.conservative.gc.Gcx.mark!(false, false, false).mark(core.internal.gc.impl.conservative.gc.Gcx.ScanRang !(false).ScanRange) (in /tmp/temp_7F2438E29F90) ==24746== by 0x4A7915: core.internal.gc.impl.conservative.gc.Gcx.markConservative!(false).mar Conservative(void*, void*) (in /tmp/temp_7F2438E29F90) ==24746== by 0x4A23BF: core.thread.threadbase.thread_scanAll(scope void(void*, void*) nothrow delegate).__lambda2!(core.thread.threadbase.ScanType, void*, void*).__lambda2(core.thread.threadbase.ScanType, void*, void*) (in /tmp/temp_7F2438E29F90) ==24746== by 0x4A7F3F: core.thread.threadbase.scanAllTypeImpl(scope void(core.thread.threadbase.ScanType, void*, void*) nothrow delegate, void*) (in /tmp/temp_7F2438E29F90) ==24746== by 0x4A7E7C: core.thread.threadbase.thread_scanAllType(scope void(core.thread.threadbase.ScanType, void*, void*) nothrow delegate).__lambda2!(void*).__lambda2(void*) (in /tmp/temp_7F2438E29F90) ==24746== by 0x494C1B: core.thread.osthread.callWithStackShell(scope void(void*) nothrow delegate) (in /tmp/temp_7F2438E29F90) ==24746== by 0x4A7E51: thread_scanAllType (in /tmp/temp_7F2438E29F90) ==24746== by 0x4A2385: thread_scanAll (in /tmp/temp_7F2438E29F90) ==24746== by 0x49FFBE: core.internal.gc.impl.conservative.gc.Gcx.markAll!(core.internal.gc.impl.conservative.gc.Gcx.markConservative!(false).mar Conservative(void*, void*)).markAll() (in /tmp/temp_7F2438E29F90) ==24746== by 0x49ADD1: core.internal.gc.impl.conservative.gc.Gcx.fullcollect(bool, bool) (in /tmp/temp_7F2438E29F90) ==24746== by 0x49FA93: core.internal.gc.impl.conservative.gc.ConservativeGC.runLocked!(core.internal.gc.impl.conservative.gc.ConservativeGC.fullCollect().go(core.internal.gc.impl.co servative.gc.Gcx*), core.internal.gc.impl.conservative.gc.Gcx*).runLocked(ref core.internal.gc.impl.conservative.gc.Gcx*) (in /tmp/temp_7F2438E29F90) ==24746== by 0x497B43: core.internal.gc.impl.conservative.gc.ConservativeGC.fullCollect() (in /tmp/temp_7F2438E29F90) ==24746== ==24746== ==24746== HEAP SUMMARY: ==24746== in use at exit: 56 bytes in 2 blocks ==24746== total heap usage: 113 allocs, 111 frees, 45,560 bytes allocated ==24746== ==24746== LEAK SUMMARY: ==24746== definitely lost: 0 bytes in 0 blocks ==24746== indirectly lost: 0 bytes in 0 blocks ==24746== possibly lost: 32 bytes in 1 blocks ==24746== still reachable: 24 bytes in 1 blocks ==24746== suppressed: 0 bytes in 0 blocks ==24746== Rerun with --leak-check=full to see details of leaked memory ==24746== ==24746== Use --track-origins=yes to see where uninitialised values come from ==24746== For lists of detected and suppressed errors, rerun with: -s ==24746== ERROR SUMMARY: 107 errors from 4 contexts (suppressed: 0 from 0) ```stuff like this is not even necessary if you dont need it now dont delcare an easy workaround is use some copy dictionary.It's not that simple. I found the following code very sympathetic. You can use the same method for structures that contain dynamic arrays and can be customized as needed... ```d alias MSS(T) = My_Static_Struct!T; struct My_Static_Struct(Type) { Type id = 0; Type[8] arr; alias T = typeof(this); disable this (); static init(Type id) { T that = void; that.id = id; return that; } } alias MDS(T) = My_Dynamic_Struct!T; struct My_Dynamic_Struct(Type) { Type id; Type[] arr; alias T = typeof(this); disable this (); static init(Type id, size_t length) { alias R = Type[]; import std.range : uninitializedArray; T that = void; that.id = id; that.arr = length.uninitializedArray!R; return that; } } import std.stdio; void main() { alias T = ubyte; MSS!T[] m1; with(MSS!T) { m1 = [ init(41), init(42) ]; } m1.writefln!"%-(%s\n%)"; MDS!T[] m2; with(MDS!T) { m2 = [ init(41, 4), init(42, 8) ]; } m2.writefln!"%-(%s\n%)"; } /* PRINTS: My_Static_Struct!ubyte(41, [0, 0, 0, 0, 0, 0, 0, 0]) My_Static_Struct!ubyte(42, [0, 0, 0, 0, 0, 0, 0, 0]) My_Dynamic_Struct!ubyte(41, [16, 32, 216, 47]) My_Dynamic_Struct!ubyte(42, [32, 32, 216, 47, 100, 127, 0, 0]) */ ``` SDB 79
Feb 26
On Wednesday, 26 February 2025 at 15:11:47 UTC, bkoie wrote:stuff like this is not even necessary if you dont need it now dont delcare an easy workaround is use some copy dictionary.I'm not sure that would work for me with the way I'm iteratively building these objects, but I'll think about it. Thank you for the suggestion.
Feb 26