Generating struct .init at run time?

Ali Çehreli acehreli at yahoo.com
Thu Jul 2 07:51:29 UTC 2020


Normally, struct .init values are known at compile time. Unfortunately, 
they add to binary size:

enum elementCount = 1024 * 1024;

struct S {
   double[elementCount] a;
}

void main() {
     S s;
     assert(typeid(S).initializer.length == double.sizeof * elementCount);
     assert(typeid(S).initializer.ptr !is null);
}

Both asserts pass: S.init is 800M and is embedded into the compiled program.

Of course, the solution is to define members with '= void':

enum elementCount = 1024 * 1024;

struct S {
   double[elementCount] a = void;  // <-- HERE
}

void main() {
     S s;
     assert(typeid(S).initializer.length == double.sizeof * elementCount);
     assert(typeid(S).initializer.ptr is null);
}

Now the program binary is 800M shorter. (Note .ptr is now null.) Also 
note that I did NOT use the following syntax because there is a dmd bug:

   auto s = S(); // Segfaults: 
https://issues.dlang.org/show_bug.cgi?id=21004

My question is: Is there a function that I can call to initialize 's' to 
the same .init value that compiler would have used:

S sInit;

shared static this() {
   defaultInitValue(&sInit);  // Does this exist?
}

I can then use sInit to copy over the bytes of all S objects in the 
program. (Both the structs and their object instantiations are all 
code-generated; so there is no usability issue. There are thousands of 
structs and the current binary size is 2G! :) )

If not, I am planning on writing the equivalent of defaultInitValue() 
that will zero-init the entire struct and then overwrite float, double, 
char, wchar, and dchar members with their respective .init values, 
recursively. Does that make sense?

Ali


More information about the Digitalmars-d-learn mailing list