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

Reply via email to