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

Fix Windows IMMNotificationClient having non-virtual destructor warning #30

Merged

Conversation

madmiraal
Copy link
Contributor

IMMNotificationClient is a Microsoft COM Interface. It is a pure virtual class that does not have a virtual destructor.

Windows Audio Session API (WASAPI) uses IMMNotificationClient to provide notifications when an audio endpoint device is added or removed, when the state or properties of an endpoint device change, or when there is a change in the default role assigned to an endpoint device.[1]

To receive notifications when the default audio endpoint device for a particular device role has changed, Rebel Engine passes a reference to an instance of CMMNotificationClient (an implementation of IMMNotificationClient) when registering the endpoint notification callback. However, CMMNotificationClient is not implemented as a COM Object. It simply extends the C++ virtual class. This results in the CMMNotificationClient declaration warning:

base class 'struct IMMNotificationClient' has accessible non-virtual destructor

This warning alerts against the possible undefined behaviour when deleting a pointer to the base class IMMNotificationClient, which would not call the destructor of CMMNotificationClient. This issue is avoided in COM programming by only creating COM Objects using CoCreateInstance and making the COM Object responsible for reference counting and deleting itself.[2][3]

To ignore the warning in Rebel Engine, we need to independently ensure that CMMNotificationClient is not deleted via a pointer to IMMNotificationClient. In Rebel Engine, CMMNotificationClient is a static variable; so it cannot be deleted. It is passed by reference (i.e. not a pointer) to RegisterEndpointNotificationCallback().

The standard implementation of IUnknown COM Interface that all COM Objects inherit, uses the Release() method to decrement the reference counter and delete itself when the reference counter reaches zero. Since CMMNotificationClient is not implemented as a COM Object, this PR also ensures that CMMNotificationClient is never returned as an interface, provides dummy implementations of the other IUnknown Interface methods, and removes the unused reference counter variable.

Finally, it also removes the unused _pEnumerator variable.

Fixes godotengine/godot#35194

[1] https://learn.microsoft.com/en-us/windows/win32/api/mmdeviceapi/nn-mmdeviceapi-immnotificationclient
[2] https://learn.microsoft.com/en-us/windows/win32/learnwin32/creating-an-object-in-com
[3] https://learn.microsoft.com/en-us/windows/win32/com/managing-object-lifetimes-through-reference-counting

@madmiraal madmiraal added the bug label Jan 27, 2024
@madmiraal madmiraal self-assigned this Jan 27, 2024
@DanielaOrtner DanielaOrtner self-requested a review January 27, 2024 10:48
Copy link
Contributor

@DanielaOrtner DanielaOrtner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the good work!

@DanielaOrtner DanielaOrtner merged commit 5355c4f into RebelToolbox:main Jan 27, 2024
13 checks passed
@madmiraal madmiraal deleted the fix-non-virtual-destructor-warning branch January 27, 2024 12:57
@madmiraal madmiraal added PR Type: Bug Fix Your current game should now work as expected. and removed bug labels May 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
PR Type: Bug Fix Your current game should now work as expected.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

-Wnon-virtual-dtor warning with MinGW/GCC in AudioDriverWasapi
2 participants