January 13, 2021
core.exception.InvalidMemoryOperationError@src\core\exception.d(647): Invalid memory operation

reference D runtime unittest executor codes
        try
        {
            fp();
            ++results.passed;
        }
        catch ( Throwable e )
        {
            import core.stdc.stdio;
            printf("%.*s(%llu): [unittest] %.*s\n",
                cast(int) e.file.length, e.file.ptr, cast(ulong) e.line,
                cast(int) e.message.length, e.message.ptr);

            if ( typeid(e) == typeid(AssertError) )
            {
                // Crude heuristic to figure whether the assertion originates in
                // the unittested module. TODO: improve.
                auto moduleName = m.name;
                if (moduleName.length && e.file.length > moduleName.length
                    && e.file[0 .. moduleName.length] == moduleName)
                {
                    // Exception originates in the same module, don't print
                    // the stack trace.
                    // TODO: omit stack trace only if assert was thrown
                    // directly by the unittest.
                    continue;
                }
            }
            // TODO: perhaps indent all of this stuff.
            _d_print_throwable(e);
        }

January 15, 2021
On 1/13/21 1:22 PM, apz28 wrote:
> core.exception.InvalidMemoryOperationError@src\core\exception.d(647): Invalid memory operation

I've struggled with this as well. It doesn't even tell you the original usage point that causes the exception.

I believe stack traces are disabled from printing on this because of the fact that it needs some memory to print the trace or walk the trace (this is fuzzy, I think it might not need memory, but I can't remember exactly).

You can override the handling of memory errors by defining it yourself:

extern(C) void onInvalidMemoryOperationError(void *pretend_sideeffect = null) @trusted pure nothrow @nogc
{
   // try to print stack trace here yourself...
}

A very *very* common reason this is triggered is because a GC destructor is trying to allocate memory (this is not allowed during GC cleanup). But without knowing the trace, it's really hard to find it.

-Steve