Windows Media Foundation MFCreateSourceReaderFromURL 函数中的内存泄漏。任何替代功能?

Posted

技术标签:

【中文标题】Windows Media Foundation MFCreateSourceReaderFromURL 函数中的内存泄漏。任何替代功能?【英文标题】:Memory leak in Windows Media Foundation MFCreateSourceReaderFromURL function. Any alternative functions? 【发布时间】:2019-10-08 09:39:47 【问题描述】:

在 Windows 10 上,Windows Media Foundation 函数 (MFCreateSourceReaderFromURL) 存在错误。每次使用后都会导致内存泄漏。 是否有任何替代功能可以在没有内存泄漏的情况下使用?看来 Windows Media 基础漏洞百出,该如何避免呢?

证明内存泄漏,运行此代码 (x86) 并观察每秒巨大的内存泄漏:

#include <mfapi.h>
#include <mfidl.h>
#include <mfreadwrite.h>
#pragma comment (lib, "Mfreadwrite.lib")
#pragma comment (lib, "Mfplat.lib")
#pragma comment (lib, "mfuuid.lib")

int main()

    while (true)
    
        if (FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
        
            return 1;
        
        if (FAILED(MFStartup(MF_VERSION)))
        
            return 1;
        
        IMFSourceReader* sourceReader = nullptr;
        if (FAILED(MFCreateSourceReaderFromURL(L"C:/any_audio_file.wav", nullptr, &sourceReader)))
        
            return 1;
        
        sourceReader->Release();
        MFShutdown();
        CoUninitialize();
    
    return 0;

Offtopic:太沮丧了。我使用 DirectShow 只是为了发现 RenderFile 网络音频流中存在错误。几天后更改为替代(Windows Media Foundation)并发现那里存在内存泄漏。微软他妈的你。

编辑:仅当文件名末尾没有 *.mp3(且内容为 mp3)时才会发生内存泄漏。或者如果文件名末尾没有 *.wav (并且内容是 wave) 例子: 有 mp3 文件“music.mp3”。将名称更改为“音乐”或“music.wav”。会发生内存泄漏。

【问题讨论】:

"...在调用此函数之前调用 CoInitialize(Ex) 和 MFStartup....":docs.microsoft.com/en-us/windows/win32/api/mfreadwrite/… @RichardCritten:实际上在 *** 的答案中忘记了这一点,但在我的代码中有这个。我在答案中添加了它。内存泄漏仍然存在并且是真实的。 谁投了反对票?我知道在这个论坛上问这个问题会导致我进入黑墙,因为它的大多数用户无能 @c3267738 请不要冒犯试图帮助你的人。 Downvote 意味着您的问题内容被认为对未来的观众没有帮助,但对投票的人没有帮助。不要个人认为。 (1) 如果您打电话给愿意为免费姓名提供时间的人:"...incompetence ..." 期待回复。 (2) 你没有提供所谓的内存泄漏的统计数据,也没有解释你的方法。 SO 帖子应该是自包含的,能够在外部运行代码,如果有额外的,那就太好了。 【参考方案1】:

根据代码,您在一个线程中多次调用 API MFShutdownCoUninitialize。这两个 API 每个线程应该只调用一次。

以下是修改后的代码,它与更真实的使用场景相匹配。您可以将此代码构建为 release(不是调试)并运行它,您会看到 60 秒内只有少量内存增加(150 kb)。小幅增加是由于 DLL 缓存大小增加(预期)和正在创建的工作队列数量增加(预期)。所以,目前我没有看到任何迹象表明存在内存泄漏。

if (FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED))) // <- Should only be called once per thread

    return 1;

if (FAILED(MFStartup(MF_VERSION))) // <- Should only be called once per thread

    return 1;


while (true)

    IMFSourceReader* sourceReader = nullptr;

    OutputDebugString(L"MFCreateSourceReaderFromURL \r\n");

    if (FAILED(MFCreateSourceReaderFromURL(L"maybe-next-time", nullptr, &sourceReader)))
    
        return 1;
    

    sourceReader->Release();

    Sleep(100); // <- Make sure to yield the processor before continuing with the loop 


MFShutdown(); // <- Should only be called once per thread
CoUninitialize(); // <- Should only be called once per thread

如果你这边的内存泄漏不是由这个引起的,你介意分享一个可以代表真实单词用法的代码示例吗?

【讨论】:

你好。您帖子中的代码为我造成了内存泄漏。只有睡眠功能会导致它累积得更慢。请注意,文件名是这里内存泄漏的关键。例如,如果您有波形文件,请将其命名为“test.mp3”或“test.123456”或“test”。只有这样才会发生内存泄漏。如果文件名是“test.wav”,则不会发生内存泄漏。我不知道这个内存使用是内存泄漏还是内部缓存造成的,但是这个内存永远不会释放(即使在 MFShutdown 和 CoUninitialize 之后),所以如果程序被设计为长时间运行,这个 api 完全无法使用。跨度> @c3267738 您是否在发布模式下运行代码?以及每分钟增加多少内存? 是的,它处于发布模式(x86,在 x64 上我没有检查)。使用 Sleep(100),每 10 分钟只有几兆字节。但是如果你在不睡眠的情况下运行它,内存增加是即时可见的 @c3267738 作为代码中的注释,为了确保在继续循环之前让处理器产生,这种情况下需要休眠。您是否正在针对内存泄漏问题开发任何真实场景? 是的,让处理器无助于内存泄漏。尽管速度较慢,但​​内存使用量是累积的,因为它每秒运行 10 次,而不是每秒运行 1000 次。但是每次调用都会发生内存泄漏。很久以前,我已经拒绝了这个损坏的库,并使用 3rd 方替代方案,没有问题。但是 Windows Media Foundation 中仍然存在内存泄漏。【参考方案2】:

这是 Microsoft Windows Media Foundation 中的一个错误。 cmets也证实了这一点。

解决方案:

不要在专业软件中使用 Microsoft Windows Media Foundation,因为它充满了隐藏的错误和内存泄漏。

【讨论】:

以上是关于Windows Media Foundation MFCreateSourceReaderFromURL 函数中的内存泄漏。任何替代功能?的主要内容,如果未能解决你的问题,请参考以下文章

Windows Media Foundation:获取 AAC 解码数据

Windows Media Foundation MFCreateSourceReaderFromURL 函数中的内存泄漏。任何替代功能?

在 Windows 10 上为 Qt 构建 WMF(Windows Media Foundation)媒体驱动程序插件

Microsoft Windows Server 2008 R2 中的 Microsoft Media Foundation

Windows 7 CoreAudio Media Foundation - IID_IAudioStreamVolume 的 uuidof

用于 Windows RT 的 Media Foundation Audio MFT 的最小实现