記 Intel 的 31.0.101.5186 版本驅動帶崩 WPF 程序

本文記錄一個 Intel 顯卡驅動問題,暫時只在 Intel UHD Graphics 770 顯卡帶 31.0.101.5186 版本的顯卡驅動時,才概率復現問題

顯卡驅動 31.0.101.5186 版本是在 2024.01.24 之前發佈的,在出現問題的設備上的表現是,運行任何的 WPF 應用程序,都會閃崩,最多窗口創建出來,但是沒有任何窗口內容,是一片黑,甚至很多時候都看不見窗口

通過事件查看器能夠看到大概如下的錯誤日誌信息內容大概如下

錯誤應用程序名稱: 林德熙.exe,版本: 2.0.12.0,時間戳: 0xce4c9261
錯誤模塊名稱: ucrtbase.dll,版本: 10.0.22621.2506,時間戳: 0x097c794c
異常代碼: 0xc0000409
錯誤偏移量: 0x000000000007f61e
錯誤進程 ID: 0x0x4E80
錯誤應用程序啓動時間: 0x0x1DA78089FE8C794
錯誤應用程序路徑: C:\lindexi\Application\林德熙.exe
錯誤模塊路徑: C:\Windows\System32\ucrtbase.dll
報告 ID: 10171c9f-c182-410f-bfa9-d162e93a9bae
錯誤程序包全名: 
錯誤程序包相對應用程序 ID: 

截圖如下

以上信息具備一點點迷惑性,因爲報告的錯誤模塊是 ucrtbase.dll 模塊。不熟悉 ucrtbase.dll 的夥伴可以在網上搜 ucrtbase.dll 崩潰問題,就會搜出來許許多多和 ucrtbase.dll 相關的信息。但其實這些方向接近全部都是錯誤的,爲什麼這麼說呢?因爲 ucrtbase.dll 是 ucrt 庫,全稱是 Universal C Runtime 是 Win 下的 C 標準庫,基本上可以認爲這是一個十分穩定的模塊,真要有出錯也是上層傳了很離譜的參數或調用形式十分詭異才可能出錯,以下是微軟官方文檔對 UCRT 的描述:

The Microsoft C Runtime Library (CRT) was refactored in Visual Studio 2015. The Standard C Library, POSIX extensions and Microsoft-specific functions, macros, and global variables were moved into a new library, the Universal C Runtime Library (Universal CRT or UCRT). The compiler-specific components of the CRT were moved into a new vcruntime library.

那爲什麼會看到這個錯誤日誌裏面的 錯誤模塊 是 ucrtbase.dll 呢?通過我從夥伴們拿到的 DUMP 進行分析可以知道,其實是因爲 UCRT 提供了 abort 方法,這個方法用於讓進程崩潰退出,導致了最後的崩潰點記錄在 ucrtbase.dll 模塊。這個 abort 方法是用在當應用程序的代碼邏輯發現出現了嚴重的異常問題,需要讓進程崩潰時調用的,一旦調用了這個 abort 方法,那進程將會崩潰掉

比方當前遇到的 Intel 驅動相關模塊內部出現了奇怪的問題,驅動模塊決定讓進程崩潰掉,所採用的方法就是間接調用了 ucrtbase.dll 的 abort 方法

通過將 Dump 文件拖入到 VisualStudio 進行混合調試分析,可以看到以下的調用堆棧

>	ucrtbase.dll!abort()
 	ucrtbase.dll!terminate()
 	ucrtbase.dll!FindHandler<__FrameHandler4>()
 	ucrtbase.dll!__InternalCxxFrameHandler<class __FrameHandler4>(struct EHExceptionRecord *,unsigned __int64 *,struct _CONTEXT *,struct _xDISPATCHER_CONTEXT *,struct FH4::FuncInfo4 *,int,unsigned __int64 *,unsigned char)
 	ucrtbase.dll!__CxxFrameHandler4()
 	ntdll.dll!RtlpExecuteHandlerForException()
 	ntdll.dll!RtlDispatchException()
 	ntdll.dll!KiUserExceptionDispatch()
 	KernelBase.dll!RaiseException()
 	igd12um64xel.dll!00007ffcc094a65f()
 	igd12um64xel.dll!00007ffcc0b51646()
 	igd12um64xel.dll!00007ffcc0a54e21()
 	igd12um64xel.dll!00007ffcc088b3cc()
 	igd12um64xel.dll!00007ffcc0851271()
 	igd12um64xel.dll!00007ffcc0850bea()
 	igd12um64xel.dll!00007ffcc086fd57()
 	igd12um64xel.dll!00007ffcc086f4e6()
 	D3D12Core.dll!NDXGI::CDevice::CreateDriverInstance(void *,void *,void *,enum D3D12DDI_CREATE_DEVICE_FLAGS)
 	D3D12Core.dll!CDevice::LLOCompleteLayerConstruction(void)
 	D3D12Core.dll!NDXGI::CDevice::LLOCompleteLayerConstruction(void)
 	D3D12.dll!00007ffce2a15bae()
 	D3D12Core.dll!D3D12CoreCreateLayeredDevice()
 	D3D12Core.dll!D3D12CoreCreateDevice()
 	D3D12Core.dll!D3D12ValidateAndCreateDevice()
 	D3D12.dll!00007ffce2a16c5b()
 	D3D12.dll!00007ffce2a1662e()
 	d3d9on12.dll!00007ffce28f4ae0()
 	d3d9on12.dll!00007ffce296df7b()
 	d3d9.dll!CreateDeviceLHDDI()
 	d3d9.dll!D3D9CreateDirectDrawObject()
 	d3d9.dll!FetchDirectDrawData()
 	d3d9.dll!InternalDirectDrawCreate()
 	d3d9.dll!CEnum::CEnum()
 	d3d9.dll!Direct3DCreate9Impl()
 	d3d9.dll!Direct3DCreate9Ex()
 	wpfgfx_v0400.dll!CD3DModuleLoaderInternal::CreateD3DObjects(struct IDirect3D9 * *,struct IDirect3D9Ex * *)
 	wpfgfx_v0400.dll!CDisplaySet::Init(void)
 	wpfgfx_v0400.dll!CDisplayManager::CreateNewDisplaySet(unsigned long,unsigned long,class CDisplaySet const * *)
 	wpfgfx_v0400.dll!CDisplayManager::DangerousGetLatestDisplaySet(class CDisplaySet const * * const)
 	wpfgfx_v0400.dll!CMILFactory::GetCurrentDisplaySet(class CDisplaySet const * *)
 	wpfgfx_v0400.dll!CMILFactory::UpdateDisplayState(bool *,int *)
 	wpfgfx_v0400.dll!CComposition::ProcessComposition(bool *)
 	wpfgfx_v0400.dll!CComposition::Compose(bool *)
 	wpfgfx_v0400.dll!CPartitionThread::RenderPartition(class Partition *)
 	wpfgfx_v0400.dll!CPartitionThread::Run(void)
 	wpfgfx_v0400.dll!CPartitionThread::ThreadMain(void *)
 	kernel32.dll!00007ffd129a257d()
 	ntdll.dll!RtlUserThreadStart()

可以看到實際的錯誤模塊是 igd12um64xel.dll 模塊,這是一個 Intel 驅動相關的模塊,這個模塊觸發了 KernelBase.dll 的 RaiseException 方法,證明出現了異常。接着這個異常沒有人處理,最後進入了 ucrtbase.dll 的 terminate 方法,再進入 abort 方法讓進程崩潰

在 WPF 的 gfx 層的 CD3DModuleLoaderInternal::CreateD3DObjects 方法裏面,將會調用 d3d9.dll!Direct3DCreate9Ex 方法,這是一個非常正常的創建 D3D9 的方法,在 d3d9.dll 的底層將會使用 d3d9on12.dll 模塊進入到 D3D12.dll 裏面,緊接着碰觸了 Intel 的驅動模塊,最後在 Intel 驅動模塊拋出異常崩掉

換句話說就是以上的錯誤內容和 ucrtbase.dll 沒有任何關係,真正的錯誤點是 igd12um64xel.dll 模塊

我將此問題報告給到 WPF 官方,詳細請看 https://github.com/dotnet/wpf/issues/8920

但預計此問題和 WPF 毫無關係,完全屬於 Intel 的問題

另外,現在 2024.03.17 最新 Intel 驅動是 31.0.101.5379 版本,如遇到問題還請大家嘗試更新一下顯卡驅動

額外,還有夥伴來和我報告說,他的應用程序只要包含中文名就能遇到相同的錯誤堆棧,只要改成英文名就沒有問題,這也很有趣。如果大家遇到類似的問題,不妨看看是不是名稱帶上中文名了,試試給他換成英文再試試。那位夥伴說只要 exe 的名稱是英文的,不帶中文的就可以正常運行,所在文件夾隨意,所在文件夾路徑帶上中文是可以的。詳細關於中文名無法啓動問題,請參閱 WPF軟件因中文名無法啓動,原因竟是英特爾驅動 – 晨旭的博客

以上提到的包含中文名就崩潰的問題,根據晨旭大佬在GitHub上的記錄,已在 Intel 的 31.0.101.5379 版本驅動修復

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章