microsoft / microsoft/DirectXShaderCompiler

Shutdown crash in SPIRV-tools due to allocator mismatch

Open
#8,086 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
C++
Stars
3.7k
Forks
900
Avg merge
2d 11h
Merged PRs (30d)
44

Description

Hi,

I'm looking into a shutdown crash we are encountering with SPIRV-tools when compiling shaders for Vulkan in UE when using a custom IMalloc instance. The callstack is the following:

dxcompiler.dll!DxcDelete(void * ptr) Line 137 C++ [Inline Frame] dxcompiler.dll!std::_Deallocate(void * _Ptr, unsigned __int64 _Bytes) Line 289 C++ [Inline Frame] dxcompiler.dll!std::_Default_allocator_traits<std::allocator<std::_List_node<spv::Op,void *>>>::deallocate(std::allocator<std::_List_node<spv::Op,void *>> & _Al, std::_List_node<spv::Op,void *> * const _Ptr, const unsigned __int64 _Count) Line 723 C++ [Inline Frame] dxcompiler.dll!std::_List_node<spv::Op,void *>::_Freenode0(std::allocator<std::_List_node<spv::Op,void *>> & _Al, std::_List_node<spv::Op,void *> * _Ptr) Line 312 C++ [Inline Frame] dxcompiler.dll!std::_List_node<spv::Op,void *>::_Freenode(std::allocator<std::_List_node<spv::Op,void *>> & _Al, std::_List_node<spv::Op,void *> * _Ptr) Line 318 C++ [Inline Frame] dxcompiler.dll!std::_List_node<spv::Op,void *>::_Free_non_head(std::allocator<std::_List_node<spv::Op,void *>> & _Al, std::_List_node<spv::Op,void *> * _Head) Line 329 C++ dxcompiler.dll!std::list<spv::Op,std::allocator<spv::Op>>::_Tidy() Line 1518 C++ ucrtbase.dll!00007ffc696abc75() Unknown ucrtbase.dll!00007ffc696ab897() Unknown ucrtbase.dll!00007ffc696ab84d() Unknown dxcompiler.dll!dllmain_crt_process_detach(const bool is_terminating) Line 182 C++ dxcompiler.dll!dllmain_dispatch(HINSTANCE__ * const instance, const unsigned long reason, void * const reserved) Line 293 C++

I've tracked this down to some function-local static standard library containers in SPIRV-tools validate_id.cpp, within the InstructionCanHaveTypeOperand and InstructionRequiresTypeOperand functions; these are allocated on first use after we've registered our custom allocator, but this override is cleared on shutdown and the DLL main detach procedure tries to free them using the default malloc instance instead. I've been able to work around these by replacing the heap-allocated std::unordered_maps with simple static arrays and using std::find.

I will note we've hit a similar issue in the past; not sure if it's possible to consider some sort of more systemic fix with how the allocator overrides work to prevent such issues in the future?

I'm also happy to submit a PR with my workaround if there's no better fix that can be suggested.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in validate_id.cpp at InstructionCanHaveTypeOperand and InstructionRequiresTypeOperand, then review the shutdown path shown in the call stack around dllmain_crt_process_detach. Reproduce compilation with a custom IMalloc and verify whether the function-local containers are freed after the allocator override is cleared. Done means the shutdown crash is resolved without regressing SPIRV-tools validation.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.