Skip to content
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

Memory leaks in MFC App that is using WinUI3 Xaml Island in DLL #10046

Open
PetrMinar opened this issue Oct 9, 2024 · 0 comments
Open

Memory leaks in MFC App that is using WinUI3 Xaml Island in DLL #10046

PetrMinar opened this issue Oct 9, 2024 · 0 comments
Labels
bug Something isn't working needs-triage Issue needs to be triaged by the area owners

Comments

@PetrMinar
Copy link

Describe the bug

I have a exe (MFC app) and dll (hosting xaml island code isolated from main app) projects written completly in C++ with help of C++/WinRT and WinAppSDK 1.6. Here is the simplified repository, where the problem can be observed.

When the application exits it reports several memory leaks that originate to the xaml framework. For example:

{2840} normal block at 0x0000017C5D4494B0, 32 bytes long.
 Data: < [       Z      > 20 5B C2 DD FB 7F 00 00 F0 5A C2 DD FB 7F 00 00 
{1204} normal block at 0x0000017C596D8060, 80 bytes long.
 Data: <   U|   ` 4]|   > A0 C3 E0 55 7C 01 00 00 60 A5 34 5D 7C 01 00 00 
{1203} normal block at 0x0000017C5D4C7AB0, 160 bytes long.
 Data: <M i c r o s o f > 4D 00 69 00 63 00 72 00 6F 00 73 00 6F 00 66 00 
{1202} normal block at 0x0000017C59710A00, 16 bytes long.
 Data: <  mY|           > 80 80 6D 59 7C 01 00 00 00 00 00 00 00 00 00 00 
{1198} normal block at 0x0000017C596D7880, 80 bytes long.
 Data: <   U|   ` G]|   > A0 C3 E0 55 7C 01 00 00 60 EB 47 5D 7C 01 00 00 
{1197} normal block at 0x0000017C597037E0, 112 bytes long.
 Data: <M i c r o s o f > 4D 00 69 00 63 00 72 00 6F 00 73 00 6F 00 66 00 
...

I was able to identify the last leak {2840} (first in list) - it is a WeakRefPtr named g_previousApplicationWeak in FrameworkApplication_Partial.cpp. When the app exits it calls FrameworkApplication::GlobalDeinit() responsible to free it. Comments in the xaml framework code clarifies the situation:
// Properly releasing the weakptr here requires vccorlib to be loaded, because it's handled
// by vccorlib140[d]!Platform::Details::ControlBlock. But this function is called during DLL
// unload, and vccorlib isn't always around. So for now we just leak the IWeakReference.
// http://task.ms/39377823 XAML can fully unload its own DLL and dependencies after use

I have found an ugly workaround to prevent this leak (reinitializing DispatcherQueueController / WindowsXamlManager after framework shutdown). The workaround can be seen in XamlIslands::Shutdown in the repository.

As for the other leaks - They are somehow related to loading compiled xaml resources. Callstack of their allocation looks like this:

 	ZXamlslands.dll!std::make_shared<winrt::ZXamlIslands::implementation::XamlTypeInfoProvider>() Line 2896
 	ZXamlslands.dll!winrt::ZXamlIslands::implementation::XamlMetaDataProvider::Provider() Line 54
 	ZXamlslands.dll!winrt::ZXamlIslands::implementation::XamlMetaDataProvider::GetXamlType(const winrt::hstring & fullName) Line 42
 	ZXamlslands.dll!winrt::ZXamlIslands::implementation::AppT<winrt::ZXamlIslands::implementation::XamlIslandApp>::GetXamlType(const winrt::hstring & fullName) Line 49
 	ZXamlslands.dll!winrt::impl::produce<winrt::ZXamlIslands::implementation::XamlIslandApp,winrt::Microsoft::UI::Xaml::Markup::IXamlMetadataProvider>::GetXamlTypeByFullName(void * fullName, void * * result) Line 858	
 	Microsoft.ui.xaml.dll!ABI::Microsoft::UI::Xaml::Phone_XamlTypeInfo::XamlLibMetadataProvider::GetXamlTypeByFullName(HSTRING__ * fullName, ABI::Microsoft::UI::Xaml::Markup::IXamlType * * value) Line 126	
 	Microsoft.ui.xaml.dll!DirectUI::MetadataAPI::ImportClassInfoFromMetadataProvider(const xstring_ptr_view & strTypeFullName, const CClassInfo * * ppType) Line 718	
 	Microsoft.ui.xaml.dll!DirectUI::MetadataAPI::TryGetClassInfoByFullName(const xstring_ptr_view & strTypeFullName, bool bSearchCustomTypesOnly, const CClassInfo * * ppType) Line 1228	
 	Microsoft.ui.xaml.dll!DirectUI::MetadataAPI::TryGetClassInfoByName(KnownNamespaceIndex eNamespaceIndex, const xstring_ptr_view & strTypeName, const CClassInfo * * ppType) Line 1270	
 	Microsoft.ui.xaml.dll!XamlManagedTypeInfoProvider::TryGetTypeWithSpecifiedNamespaceId(const KnownNamespaceIndex nNamespaceIndex, const xstring_ptr & spTypeName, XamlTypeToken * ptokType) Line 691	
 	Microsoft.ui.xaml.dll!XamlManagedTypeInfoProvider::ResolveTypeName(const XamlTypeNamespaceToken inNamespaceToken, const xstring_ptr & inTypeName, XamlTypeToken & rXamlType) Line 240	
 	Microsoft.ui.xaml.dll!XamlNativeTypeInfoProvider::ResolveTypeName(const XamlTypeNamespaceToken inNamespaceToken, const xstring_ptr & inTypeName, XamlTypeToken & rXamlType) Line 251	
 	Microsoft.ui.xaml.dll!XamlTypeNamespace::GetXamlType(const xstring_ptr & inTypeName, std::shared_ptr<XamlType> & outType) Line 43	
 	Microsoft.ui.xaml.dll!XamlXmlNamespace::GetXamlTypeImpl(const xstring_ptr & inTypeName, std::shared_ptr<XamlType> & outType) Line 86	
 	Microsoft.ui.xaml.dll!XamlXmlNamespace::GetXamlType(const xstring_ptr & inTypeName, std::shared_ptr<XamlType> & outType) Line 39	
 	Microsoft.ui.xaml.dll!XamlBinaryMetadataReader2::LoadType(unsigned int index) Line 252	
 	Microsoft.ui.xaml.dll!XamlBinaryMetadataReader2::GetType(const unsigned int index, std::shared_ptr<XamlType> & result) Line 600	
 	[Inline Frame] Microsoft.ui.xaml.dll!XamlBinaryMetadataReader2::GetType(const PersistedXamlNode2 &) Line 660	
 	Microsoft.ui.xaml.dll!XamlBinaryFormatSubReader2::ReadXamlType() Line 810	
 	Microsoft.ui.xaml.dll!XamlBinaryFormatSubReader2::ReadCreateTypeBeginInitNode() Line 607	
 	Microsoft.ui.xaml.dll!XamlBinaryFormatSubReader2::TryRead(ObjectWriterNode & currentXamlNode) Line 186	
 	Microsoft.ui.xaml.dll!XamlBinaryFormatSubReader2::TryReadHRESULT(ObjectWriterNode & currentXamlNode, bool * endOfStream) Line 40	
 	Microsoft.ui.xaml.dll!CParser::LoadXamlCore(CCoreServices * pCore, const CParserSettings & parserSettings, const Parser::XamlBuffer & buffer, CDependencyObject * * ppDependencyObject, const xstring_ptr_view & strSourceAssemblyName, const std::array<unsigned char,64> &) Line 269	
 	[Inline Frame] Microsoft.ui.xaml.dll!CParser::LoadXaml(CCoreServices *) Line 34	
 	Microsoft.ui.xaml.dll!CCoreServices::ParseXamlWithExistingFrameworkRoot(const Parser::XamlBuffer & buffer, CDependencyObject * pExistingFrameworkRoot, const xstring_ptr_view & strSourceAssemblyName, const xstring_ptr_view & strXamlResourceUri, const bool expandTemplatesDuringParse, CDependencyObject * * ppDependencyObject) Line 3628	
 	Microsoft.ui.xaml.dll!CApplication::LoadComponent(CCoreServices * pCore, CDependencyObject * pComponent, IPALUri * pUri) Line 493	
 	Microsoft.ui.xaml.dll!CoreImports::Application_LoadComponent(CCoreServices * pCore, CDependencyObject * pComponent, const xstring_ptr & strUri, ComponentResourceLocation resourceLocation) Line 264	
 	Microsoft.ui.xaml.dll!DirectUI::FrameworkApplication::LoadComponent(IInspectable * pComponent, const xstring_ptr & strUri, ABI::Microsoft::UI::Xaml::Controls::Primitives::ComponentResourceLocation resourceLocation) Line 553	
 	Microsoft.ui.xaml.dll!DirectUI::FrameworkApplicationFactory::LoadComponentWithResourceLocationImpl(IInspectable * pComponent, ABI::Windows::Foundation::IUriRuntimeClass * pUri, ABI::Microsoft::UI::Xaml::Controls::Primitives::ComponentResourceLocation resourceLocation) Line 492	
 	Microsoft.ui.xaml.dll!DirectUI::FrameworkApplicationFactory::LoadComponentWithResourceLocation(IInspectable * pComponent, ABI::Windows::Foundation::IUriRuntimeClass * pResourceLocator, ABI::Microsoft::UI::Xaml::Controls::Primitives::ComponentResourceLocation componentResourceLocation) Line 879
 	[Inline Frame] Microsoft.ui.xaml.dll!DirectUI::FrameworkApplicationFactory::LoadComponentImpl(IInspectable *) Line 475
 	Microsoft.ui.xaml.dll!DirectUI::FrameworkApplicationFactory::LoadComponent(IInspectable * pComponent, ABI::Windows::Foundation::IUriRuntimeClass * pResourceLocator) Line 861
 	ZXamlslands.dll!winrt::impl::consume_Microsoft_UI_Xaml_IApplicationStatics<winrt::Microsoft::UI::Xaml::IApplicationStatics>::LoadComponent(const winrt::Windows::Foundation::IInspectable & component, const winrt::Windows::Foundation::Uri & resourceLocator) Line 188	
 	ZXamlslands.dll!winrt::Microsoft::UI::Xaml::Application::LoadComponent::__l2::<lambda_1>::operator()(const winrt::Microsoft::UI::Xaml::IApplicationStatics & f) Line 12465	
 	ZXamlslands.dll!winrt::impl::factory_cache_entry<winrt::Microsoft::UI::Xaml::Application,winrt::Microsoft::UI::Xaml::IApplicationStatics>::call<`winrt::Microsoft::UI::Xaml::Application::LoadComponent'::`2'::<lambda_1> &>(winrt::Microsoft::UI::Xaml::Application::LoadComponent::__l2::<lambda_1> & callback) Line 6419	
 	ZXamlslands.dll!winrt::impl::call_factory<winrt::Microsoft::UI::Xaml::Application,winrt::Microsoft::UI::Xaml::IApplicationStatics,`winrt::Microsoft::UI::Xaml::Application::LoadComponent'::`2'::<lambda_1>>(winrt::Microsoft::UI::Xaml::Application::LoadComponent::__l2::<lambda_1> && callback) Line 6441	
 	ZXamlslands.dll!winrt::Microsoft::UI::Xaml::Application::LoadComponent(const winrt::Windows::Foundation::IInspectable & component, const winrt::Windows::Foundation::Uri & resourceLocator) Line 12465	
 	ZXamlslands.dll!winrt::ZXamlIslands::implementation::AppT<winrt::ZXamlIslands::implementation::XamlIslandApp>::InitializeComponent() Line 38
 	ZXamlslands.dll!winrt::impl::create_and_initialize<winrt::ZXamlIslands::implementation::XamlIslandApp>() Line 7917	
 	ZXamlslands.dll!winrt::make<winrt::ZXamlIslands::implementation::XamlIslandApp>() Line 7998	
 	ZXamlslands.dll!XamlIslands::XxxIslandApp() Line 16	
 	ZXamlslands.dll!XamlIslands::XxxInitializeForCurrentThread::__l2::<lambda_1>::operator()() Line 44	
 	ZXamlslands.dll!XamlIslands::XxxInitializeForCurrentThread() Line 35	
 	ZXamlslands.dll!XamlIslands::IslandWndT::Create(std::shared_ptr<XamlIslands::IslandWndT> & Island, HWND__ * Parent, XamlIslands::PageT Page) Line 68	
 	ZXamlslands.dll!XamlIslands::Create(std::shared_ptr<XamlIslands::IslandWndT> & Island, HWND__ * Parent, XamlIslands::PageT Page) Line 171	
 	MFCApp.exe!CMainFrame::OnCreate(tagCREATESTRUCTW * lpCreateStruct) Line 64	
 	mfc140ud.dll!CWnd::OnWndMsg(unsigned int message, unsigned __int64 wParam, __int64 lParam, __int64 * pResult) Line 2409
 	mfc140ud.dll!CWnd::WindowProc(unsigned int message, unsigned __int64 wParam, __int64 lParam) Line 2100
 	mfc140ud.dll!AfxCallWndProc(CWnd * pWnd, HWND__ * hWnd, unsigned int nMsg, unsigned __int64 wParam, __int64 lParam) Line 265
 	mfc140ud.dll!AfxWndProc(HWND__ * hWnd, unsigned int nMsg, unsigned __int64 wParam, __int64 lParam) Line 418
 	mfc140ud.dll!AfxWndProcBase(HWND__ * hWnd, unsigned int nMsg, unsigned __int64 wParam, __int64 lParam) Line 299
 	user32.dll!UserCallWinProcCheckWow()	
 	user32.dll!DispatchClientMessage()	
 	user32.dll!__fnINLPCREATESTRUCT()	
 	ntdll.dll!00007ffca9874114()	
 	win32u.dll!00007ffca6e32294()	
 	user32.dll!VerNtUserCreateWindowEx()	
 	user32.dll!CreateWindowInternal()	
 	user32.dll!CreateWindowExW()	
 	mfc140ud.dll!IsolationAwareCreateWindowExW(unsigned long dwExStyle, const wchar_t * lpClassName, const wchar_t * lpWindowName, unsigned long dwStyle, int X, int Y, int nWidth, int nHeight, HWND__ * hWndParent, HMENU__ * hMenu, HINSTANCE__ * hInstance, void * lpParam) Line 449
 	mfc140ud.dll!CWnd::CreateEx(unsigned long dwExStyle, const wchar_t * lpszClassName, const wchar_t * lpszWindowName, unsigned long dwStyle, int x, int y, int nWidth, int nHeight, HWND__ * hWndParent, HMENU__ * nIDorHMenu, void * lpParam) Line 727
 	mfc140ud.dll!CFrameWnd::Create(const wchar_t * lpszClassName, const wchar_t * lpszWindowName, unsigned long dwStyle, const tagRECT & rect, CWnd * pParentWnd, const wchar_t * lpszMenuName, unsigned long dwExStyle, CCreateContext * pContext) Line 622
 	mfc140ud.dll!CFrameWnd::LoadFrame(unsigned int nIDResource, unsigned long dwDefaultStyle, CWnd * pParentWnd, CCreateContext * pContext) Line 755
 	MFCApp.exe!CMFCWinUI3App::InitInstance() Line 102	
 	mfc140ud.dll!AfxWinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, wchar_t * lpCmdLine, int nCmdShow) Line 37
 	MFCApp.exe!wWinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, wchar_t * lpCmdLine, int nCmdShow) Line 26	
 	MFCApp.exe!invoke_main() Line 123
 	MFCApp.exe!__scrt_common_main_seh() Line 288
 	MFCApp.exe!__scrt_common_main() Line 331
 	MFCApp.exe!wWinMainCRTStartup(void * __formal) Line 17
 	kernel32.dll!00007ffca93d257d()	
 	ntdll.dll!00007ffca982af08()	

Steps to reproduce the bug

Run the app in provided repository.

Expected behavior

No leaks after application exit.
Or having a "shutdown function" to do final cleanup before app exit would be enough.
Or mark the allocations as _IGNORE_BLOCK so they are not reported as leak by vc runtime.

Screenshots

No response

NuGet package version

WinUI 3 - Windows App SDK 1.6.1: 1.6.240923002

Windows version

Windows 11 (22H2): Build 22621

Additional context

No response

@PetrMinar PetrMinar added the bug Something isn't working label Oct 9, 2024
@microsoft-github-policy-service microsoft-github-policy-service bot added the needs-triage Issue needs to be triaged by the area owners label Oct 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working needs-triage Issue needs to be triaged by the area owners
Projects
None yet
Development

No branches or pull requests

1 participant