View Issue Details

IDProjectCategoryView StatusLast Update
0004168The Dark ModSEEDpublic29.06.2015 04:09
ReporterSteveL Assigned ToSteveL  
PriorityhighSeverityblockReproducibilityalways
Status resolvedResolutionfixed 
Product VersionTDM 2.03 
Target VersionTDM 2.04Fixed in VersionTDM 2.04 
Summary0004168: SEED deletes heap memory it doesn't own
DescriptionSEED causes debug builds to crash by deleting heap memory that it doesn't own. Possibly a double-deletion. This makes maps using it impossible to debug without deleting all the SEED entities first, invalidating save games from those maps, and it'll prevent us extending the system to cover modelled architecture.
Steps To ReproduceHave SEED combine a pair of LOD models. In play, at the first LOD transition, the game will crash with an assertion error.
Additional InformationThe crash arises in unrelated code, caused by heap corruption, after a map shut down has already been triggered.

Call stack for the point where the map shut down gets triggered:

- TheDarkMod.exe!_wassert(const wchar_t * expr, const wchar_t * filename, unsigned int lineno) Line 314
- TheDarkMod.exe!idDynamicBlockAlloc<idDrawVert,1048576,1024>::FreeInternal(idDynamicBlock<idDrawVert> * block) Line 815
- TheDarkMod.exe!idDynamicBlockAlloc<idDrawVert,1048576,1024>::Free(idDrawVert * ptr) Line 646
- TheDarkMod.exe!R_ReallyFreeStaticTriSurf(srfTriangles_s * tri) Line 381
- TheDarkMod.exe!R_FreeDeferredTriSurfs(frameData_t * frame) Line 468
- TheDarkMod.exe!R_ToggleSmpFrame() Line 181
- TheDarkMod.exe!idRenderSystemLocal::EndFrame(int * frontEndMsec, int * backEndMsec) Line 743

If there's a double deletion, the problem probably happens much earlier in the frame.
TagsNo tags attached.

Relationships

related to 0004169 closedSteveL Let same-textured surfaces from different models be drawn in a single draw call 

Activities

SteveL

SteveL

27.06.2015 22:45

reporter   ~0007604

The problem is in CStaticMulti::UpdateRenderModel. CStaticMulti is the class for seed-combined entities.

I haven't followed the path all the way through to find out exactly how the heap corruption comes about, but the problem arises because of the re-use of a render model pointer for a newly-constructed combined model, which was probably done to avoid an allocation.

When the native game code changes a model, it always calls gameRenderWorld->FreeEntityDef, and uses a fresh pointer for a different model. There are parts of the engine code that *rely* on hModel pointers always pointing to the same model, for example idRenderWorldLocal::UpdateEntityDef which compares the old and the new hModel pointers for an entity when deciding whether it can leave decals in place.

The renderer's model code does look like you *should* be able to construct a new model using an existing pointer in this way, because it provides an InitEmpty() method that clears the surfaces of the model. But in the native code only dynamic models use that method, not statics, and for dynamic models there's no concept of consistency from frame to frame.

Changing the code to clear the entity def and use a newly allocated pointer for the new model stops the problem. That's also what the (non-buggy) LOD code does.
SteveL

SteveL

28.06.2015 20:54

reporter   ~0007605

At rev 6511

/trunk/game/StaticMulti.cpp
/trunk/game/StaticMulti.h
grayman

grayman

29.06.2015 04:09

viewer   ~0007607

Nice catch.

Issue History

Date Modified Username Field Change
27.06.2015 15:10 SteveL New Issue
27.06.2015 15:10 SteveL Status new => assigned
27.06.2015 15:10 SteveL Assigned To => SteveL
27.06.2015 15:12 SteveL Additional Information Updated
27.06.2015 15:12 SteveL Description Updated
27.06.2015 22:45 SteveL Note Added: 0007604
28.06.2015 20:54 SteveL Note Added: 0007605
28.06.2015 20:54 SteveL Status assigned => resolved
28.06.2015 20:54 SteveL Fixed in Version => TDM 2.04
28.06.2015 20:54 SteveL Resolution open => fixed
28.06.2015 20:58 SteveL Relationship added related to 0004169
29.06.2015 04:09 grayman Note Added: 0007607