The constructor just initializes a single integer field to zero. Rest is by the book. There is only one global variable of my value-type (the type's name is FuncBind) in that module, by step debugging I see that ExecuteNext() reaches asBC_ALLOC (with a script object), then executes the following line
asDWORD *mem = (asDWORD*)m_engine->CallAlloc(objType);
where objType is what it's supposed to be - FuncBind. However at this point the func variable (which I understand is supposed to be the id of the type's constructor) is the id of some unrelated function. This function is called with CallSystemFunction, and the crash happens soon later on
if( a ) *a = mem;
at which point I see a corrupted stack.
It might be important that in our case the registration of certain global functions happens in between loading of modules (either from source or bytecode). Each module has a list of "dependencies" which are registered to the engine just prior to the compilation of this module, unless they are already loaded. The constructor that fails to be called (and the function called instead of it) are both registered like this.
edit: I can also reproduce this with func being the id of a nonregistered function, i.e. a script function. Naturally, CallSystemFunction fails with them on the spot. I have a question, where in ReadInner() "linking stage" there is the translation of registered object's constructor calls? And where are ids of these actually stored - I see that asBC_ALLOC opcodes are followed by a (correct) type pointer, and then pointer to function id - to where do those pointers point specifically?