-
Notifications
You must be signed in to change notification settings - Fork 362
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Assertion "st->c->value.argSize == func->parmTotal" from some Scripts #303
Comments
If a "class" (object) in a Script has multiple member function prototypes, and one function implementation later calls another before that is implemented, there was an assertion when the script was parsed (at map start), because the size of function arguments at the call-site didn't match what the function expected - because the function hadn't calculated that size yet, that only happened once its own implementation was parsed. Now it's calculated (and stored) when the prototype/declaration is parsed to prevent this issue, which seems to be kinda common with Mods, esp. Script-only mods, as the release game DLLs had Assertions disabled.
I think I have a "proper" fix for this, see the Not sure I dare to merge this before 1.5.1; testing+feedback is welcome! |
Here is a windows build (latest git master + this script fix for base.dll and d3xp.dll): dhewm3-scriptfix.zip As the script interpreter is part of the gamecode this must be fixed separately in every mod that needs its own DLL, so right now only the main game and RoE are fixed (and mods without their own DLL that use base.dll). |
dhewm3.exe do not unload properly from RAM. Process stay in memory. |
There's some kind of crash when ending the game due to a bug in the current openal-soft version - but I've never seen it not exit at all |
So, I have a situation during test when 7 processes named dhewm3.exe exists in memory. |
Weird - I'll have to test on my old Win7 machine. |
My test: On version 1.5.1pre1304 there is no problem. |
So the problem doesn't happen if you don't load the map? Can you try if the problem goes away if you use 1.5.1rc2 with the OpenAL32.dll from 1.5.1pre ? |
Made a test: just load dhewm3 without load any map: still stay in memory. Upd: test with OpenAL from 1.5.1.per1304: dhewm3 unload from RAM correctly. |
@AntonieS: Can you try if it works better when replacing OpenAL32.dll with this one: |
With new OpenAL.dll work well. But in Lost Mission crush when load exis1. |
I need more information on the exis1 crash. |
I became crash only when load savegame (while loading game hangs). Whean load from console - all Ok. |
With new dll sound is much better. In both rc2 and pre2 versions. |
It corrupted the stack when called with buffers allocated on the stack and numSamples that are not a multiple of four, apparently, by writing 4 floats too many, at least in the 22KHz Stereo case.. This caused the crash described in #303 (comment) Now it just uses the generic C code, like all platforms besides MSVC/x86 already do.
If a "class" (object) in a Script has multiple member function prototypes, and one function implementation later calls another before that is implemented, there was an assertion when the script was parsed (at map start), because the size of function arguments at the call-site didn't match what the function expected - because the function hadn't calculated that size yet, that only happened once its own implementation was parsed. Now it's calculated (and stored) when the prototype/declaration is parsed to prevent this issue, which seems to be kinda common with Mods, esp. Script-only mods, as the release game DLLs had Assertions disabled.
@AntonieS: The crash should be fixed in the latest build, can you test it? dhewm3_1.5.1_RC3_win32.zip |
Now all works fine. Thanks. |
Good to know, thanks for testing! By the way, I also put the fix for that script assertion into the master branch and it's also in the 1.5.1 RC3 build linked above, so I guess this can be closed |
It corrupted the stack when called with buffers allocated on the stack and numSamples that are not a multiple of four, apparently, by writing 4 floats too many, at least in the 22KHz Stereo case.. This caused the crash described in dhewm/dhewm3#303 (comment) Now it just uses the generic C code, like all platforms besides MSVC/x86 already do.
It corrupted the stack when called with buffers allocated on the stack and numSamples that are not a multiple of four, apparently, by writing 4 floats too many, at least in the 22KHz Stereo case.. This caused the crash described in dhewm/dhewm3#303 (comment) Now it just uses the generic C code, like all platforms besides MSVC/x86 already do.
It corrupted the stack when called with buffers allocated on the stack and numSamples that are not a multiple of four, apparently, by writing 4 floats too many, at least in the 22KHz Stereo case.. This caused the crash described in dhewm/dhewm3#303 (comment) Now it just uses the generic C code, like all platforms besides MSVC/x86 already do.
It corrupted the stack when called with buffers allocated on the stack and numSamples that are not a multiple of four, apparently, by writing 4 floats too many, at least in the 22KHz Stereo case.. This caused the crash described in dhewm/dhewm3#303 (comment) Now it just uses the generic C code, like all platforms besides MSVC/x86 already do.
It corrupted the stack when called with buffers allocated on the stack and numSamples that are not a multiple of four, apparently, by writing 4 floats too many, at least in the 22KHz Stereo case.. This caused the crash described in dhewm/dhewm3#303 (comment) Now it just uses the generic C code, like all platforms besides MSVC/x86 already do.
It corrupted the stack when called with buffers allocated on the stack and numSamples that are not a multiple of four, apparently, by writing 4 floats too many, at least in the 22KHz Stereo case.. This caused the crash described in dhewm/dhewm3#303 (comment) Now it just uses the generic C code, like all platforms besides MSVC/x86 already do.
It corrupted the stack when called with buffers allocated on the stack and numSamples that are not a multiple of four, apparently, by writing 4 floats too many, at least in the 22KHz Stereo case.. This caused the crash described in dhewm/dhewm3#303 (comment) Now it just uses the generic C code, like all platforms besides MSVC/x86 already do.
"Fix "t->c->value.argSize == func->parmTotal" Assertion in Scripts, #303" had broken old savegames because the script checksum (idProgram::CalculateChecksum()) changed, see #344. This is fixed now, also the BUILD_NUMBER is increased so old savegames can be identified for a workaround. Don't use this commit without the next one which will further modify the savegame format (for the new BUILD_NUMBER 1305) Before merging this to master I'll also modify d3xp/ accordingly
"Fix "t->c->value.argSize == func->parmTotal" Assertion in Scripts, #303" had broken old savegames because the script checksum (idProgram::CalculateChecksum()) changed, see #344. This is fixed now, also the BUILD_NUMBER is increased so old savegames can be identified for a workaround. Don't use this commit without the next one which will further modify the savegame format (for the new BUILD_NUMBER 1305)
"Fix "t->c->value.argSize == func->parmTotal" Assertion in Scripts, #303" had broken old savegames because the script checksum (idProgram::CalculateChecksum()) changed, see #344. This is fixed now, also the BUILD_NUMBER is increased so old savegames can be identified for a workaround. Don't use this commit without the next one which will further modify the savegame format (for the new BUILD_NUMBER 1305)
It corrupted the stack when called with buffers allocated on the stack and numSamples that are not a multiple of four, apparently, by writing 4 floats too many, at least in the 22KHz Stereo case.. This caused the crash described in dhewm/dhewm3#303 (comment) Now it just uses the generic C code, like all platforms besides MSVC/x86 already do.
It corrupted the stack when called with buffers allocated on the stack and numSamples that are not a multiple of four, apparently, by writing 4 floats too many, at least in the 22KHz Stereo case.. This caused the crash described in dhewm#303 (comment) Now it just uses the generic C code, like all platforms besides MSVC/x86 already do.
…ewm#303 If a "class" (object) in a Script has multiple member function prototypes, and one function implementation later calls another before that is implemented, there was an assertion when the script was parsed (at map start), because the size of function arguments at the call-site didn't match what the function expected - because the function hadn't calculated that size yet, that only happened once its own implementation was parsed. Now it's calculated (and stored) when the prototype/declaration is parsed to prevent this issue, which seems to be kinda common with Mods, esp. Script-only mods, as the release game DLLs had Assertions disabled.
"Fix "t->c->value.argSize == func->parmTotal" Assertion in Scripts, dhewm#303" had broken old savegames because the script checksum (idProgram::CalculateChecksum()) changed, see dhewm#344. This is fixed now, also the BUILD_NUMBER is increased so old savegames can be identified for a workaround. Don't use this commit without the next one which will further modify the savegame format (for the new BUILD_NUMBER 1305)
It corrupted the stack when called with buffers allocated on the stack and numSamples that are not a multiple of four, apparently, by writing 4 floats too many, at least in the 22KHz Stereo case.. This caused the crash described in dhewm/dhewm3#303 (comment) Now it just uses the generic C code, like all platforms besides MSVC/x86 already do.
It corrupted the stack when called with buffers allocated on the stack and numSamples that are not a multiple of four, apparently, by writing 4 floats too many, at least in the 22KHz Stereo case.. This caused the crash described in dhewm/dhewm3#303 (comment) Now it just uses the generic C code, like all platforms besides MSVC/x86 already do.
I ran into an assertion in the script interpreter when testing a dhewm3 mod in a Debug build: "st->c->value.argSize == func->parmTotal" from
idInterpreter::Execute()
.When ignoring or commenting out that assertion, another one in
idInterpreter::LeaveFunction()
triggers: "localstackUsed == localstackBase".It turned out that the problem was the following:
We have a player "class" like:
and then below there's implementations for those methods - and
init()
creates a thread withcheck_music_volume()
, but thecheck_music_volume()
implementation is below theinit()
implementation!Now when I start a map and that code gets executed (player::init() is called when the player spawns), I get the aforementioned assertion (if assertions are enabled, like in debug builds), because the opcode pretends that the function call has no arguments at all (that need to be passed when calling), while in reality the "self" pointer to the player object is implicitly passed (so check_music_volume() knows what player object it belongs to and can access its fields, like
music_volume
).This can be "fixed" by moving
void player::check_music_volume() { ... }
above
void player::init() { ... }
According to http://idtechforums.fuzzylogicinc.com/index.php?topic=897.0 this is a known problem in Doom3; it has also been mentioned in #204 (incl. the workaround of reordering); weirdly it doesn't seem to be documented anywhere else.
#265 (comment) also mentions this problem, with the Yet another flashlight Mod (which is script-only).
What is going wrong in the C++ Code
Now the problem was that the script compiler, when generating the ops for that thread creation
(
idCompiler::ParseObjectCall() => idCompiler::EmitFunctionParms(), op == OP_OBJTHREAD
)it sets the wrong size for the statement, taken from
func->value.functionPtr->parmTotal
.This happens at game startup, when all the scripts are parsed and compiled.
The reason that
parmTotal
for the "check_music_volume" function_t is0
(while it should be8
, at least on my machine, for theself
object reference) is, that even though anidTypeDef
with typeev_function
and thefunction_t
is created whenobject player : player_base {
is parsed and it encounters thevoid check_music_volume();
line,parmTotal
is not calculated and set until the implementation of the function is parsed much later (when it reachesvoid player::check_music_volume() {
way below).It all happens in
idCompiler::ParseFunctionDef(...)
- that function is called both for the function declaration/prototype (void check_music_volume();
) is called fromidCompiler::ParseObjectDef()
when it parses theplayer
object, [i]and[/i] later when parsing the [i]implementation[/i] (after the bytecode forplayer::init()
is generated), in that case it's called fromParseNamespace() => ParseDefs() => ParseFunctionDef()
.The reason the second call calculates and sets
parmTotal
(and alsonumParams
) correctly (and the first call doesn't) is the following lines inidCompiler::ParseFunctionDef(...)
:So when parsing the method declaration/prototype
ParseFunctionDef(...)
returns before doing the calculations for stack space needed by function parameters - this is only done when parsing the implementation!So, if the method is called in the script file [i]before[/i] the the implementation,
assert( st->c->value.argSize == func->parmTotal );
inidInterpreter::Execute()
fails.I have no idea why the stack space calculation etc isn't just done when parsing the prototype.
A Workaround
Modify
idCompiler::EmitFunctionParms()
like this:A proper solution would be to do the full parameter calculation in
ParseFunctionDef()
when parsing the function prototype and not just when parsing the implementation - but then you gotta make sure the parameters and their sizes aren't added twice (when parsing the prototype and when parsing the implementation), of course, so it needs a bit of thinking and cautiousness.(I originally documented this at http://idtechforums.fuzzylogicinc.com/index.php?topic=897.0 but I think we should have a proper issue here so I hopefully don't forget to "properly" fix it eventually)
The text was updated successfully, but these errors were encountered: