Environment
- Compiler: Intel oneAPI DPC++/C++ Compiler (ICX), which is LLVM/Clang-based and defines both
_MSC_VER and __clang__
- Platform: Windows x64
- Build: mimalloc as a shared library (
MI_SHARED_LIB=1) with malloc override (MI_MALLOC_OVERRIDE=1)
- MSVC: Works correctly (tested with v145 toolset)
Symptom
When mimalloc is compiled as a DLL using Intel ICX, the process crashes immediately at startup:
Exception thrown at 0x00007FFE7F06AA73 (ntdll.dll) in arma3_x64.exe:
0xC0000005: Access violation writing location 0x0000000000000024.
The call stack shows only ntdll.dll and kernel32.dll frames — no user code frames are visible.
Defining MI_WIN_NO_RAW_DLLMAIN eliminates the crash entirely.
Root Cause
When MI_WIN_NO_RAW_DLLMAIN is not defined, mimalloc uses the CRT's _pRawDllMain mechanism for DLL initialization:
// src/prim/windows/prim.c
static BOOL NTAPI mi_dll_main_raw(PVOID module, DWORD reason, LPVOID reserved) {
mi_win_main(module, reason, reserved);
return TRUE;
}
extern "C" PVOID _pRawDllMain = &mi_dll_main_raw;
The CRT's DllMainCRTStartup reads _pRawDllMain and calls it before any other CRT initialization. This is the point where mimalloc initializes its thread-local default heap (_mi_heap_default), switching it from _mi_heap_empty (whose tld field is NULL) to _mi_heap_main (which has a valid tld).
ICX issues a warning on this line:
warning: implicit conversion between pointer-to-function and pointer-to-object
is a Microsoft extension [-Wmicrosoft-cast]
More critically, the ICX-compiled DLL does not appear to deliver _pRawDllMain to the CRT correctly. As a result, the CRT never calls mi_dll_main_raw, and the entire initialization chain (mi_win_main → mi_win_tls_init → _mi_auto_process_init → mi_process_init) is skipped.
The subsequent crash at address 0x24 is a NULL-pointer dereference through _mi_heap_empty.tld:
| Structure |
Field |
Offset |
mi_tld_t |
segments (starts at offset 0x20) |
0x20 |
mi_segments_tld_t |
spans[0] (+ 0x04 into segments) |
0x24 |
Any allocation attempt dereferences heap->tld->segments... → writes to NULL + 0x24 → 0xC0000005.
Workaround
Define MI_WIN_NO_RAW_DLLMAIN in the preprocessor definitions. This makes mimalloc use an explicit DllMain entry point instead of _pRawDllMain, which works correctly with ICX:
#elif defined(MI_SHARED_LIB)
BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved) {
mi_win_main((PVOID)inst,reason,reserved);
return TRUE;
}
Suggested Fix
Auto-detect ICX/Clang when building as a shared library on Windows and use DllMain instead of _pRawDllMain. The following can be added before the #ifndef MI_WIN_NO_RAW_DLLMAIN check in src/prim/windows/prim.c:
#if defined(__clang__) && defined(MI_SHARED_LIB) && !defined(MI_WIN_NO_RAW_DLLMAIN)
#define MI_WIN_NO_RAW_DLLMAIN 1
#endif
Environment
_MSC_VERand__clang__MI_SHARED_LIB=1) with malloc override (MI_MALLOC_OVERRIDE=1)Symptom
When mimalloc is compiled as a DLL using Intel ICX, the process crashes immediately at startup:
The call stack shows only ntdll.dll and kernel32.dll frames — no user code frames are visible.
Defining
MI_WIN_NO_RAW_DLLMAINeliminates the crash entirely.Root Cause
When
MI_WIN_NO_RAW_DLLMAINis not defined, mimalloc uses the CRT's_pRawDllMainmechanism for DLL initialization:The CRT's
DllMainCRTStartupreads_pRawDllMainand calls it before any other CRT initialization. This is the point where mimalloc initializes its thread-local default heap (_mi_heap_default), switching it from_mi_heap_empty(whosetldfield isNULL) to_mi_heap_main(which has a validtld).ICX issues a warning on this line:
More critically, the ICX-compiled DLL does not appear to deliver
_pRawDllMainto the CRT correctly. As a result, the CRT never callsmi_dll_main_raw, and the entire initialization chain (mi_win_main→mi_win_tls_init→_mi_auto_process_init→mi_process_init) is skipped.The subsequent crash at address
0x24is a NULL-pointer dereference through_mi_heap_empty.tld:mi_tld_tsegments(starts at offset0x20)0x20mi_segments_tld_tspans[0](+0x04intosegments)0x24Any allocation attempt dereferences
heap->tld->segments...→ writes toNULL + 0x24→0xC0000005.Workaround
Define
MI_WIN_NO_RAW_DLLMAINin the preprocessor definitions. This makes mimalloc use an explicitDllMainentry point instead of_pRawDllMain, which works correctly with ICX:Suggested Fix
Auto-detect ICX/Clang when building as a shared library on Windows and use
DllMaininstead of_pRawDllMain. The following can be added before the#ifndef MI_WIN_NO_RAW_DLLMAINcheck insrc/prim/windows/prim.c: