Windows平台Qt 5.15.18中QAudioDeviceInfo疑似存在内存泄漏
Qt 5.15.18 Windows平台QAudioDeviceInfo::availableDevices()内存泄漏问题
问题概述
在Windows平台使用Qt 5.15.18版本时,调用QAudioDeviceInfo::availableDevices()存在持续内存泄漏问题(暂未测试其他平台)。
背景
需要实现实时检测Windows上特定音频设备是否存在的功能,因此周期性调用QAudioDeviceInfo::availableDevices()列出音频输入设备,但发现进程内存占用持续增长,疑似内存泄漏。
最小复现示例
#include <QApplication> #include <QAudioDeviceInfo> #include <QDebug> #include <QPushButton> #include <QTimer> #include <QVBoxLayout> int main(int argc, char *argv[]) { QApplication app(argc, argv); QWidget *w = new QWidget(); w->resize(400, 300); w->show(); QTimer *timer = new QTimer(w); QObject::connect(timer, &QTimer::timeout, w, [w]() { qDebug() << "Timer timeout"; // 获取可用音频输入设备列表 QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput); // 遍历设备并打印名称 for (const QAudioDeviceInfo &device : devices) { qDebug() << "Device Name:" << device.deviceName(); } }); // 每100ms触发一次设备检测 timer->start(100); int ret = app.exec(); delete w; return ret; }
观测到的行为
- 在Windows上运行该代码时,进程内存占用(可通过任务管理器/资源监视器查看)随时间持续增加;
- 尽管
QList<QAudioDeviceInfo>是栈分配变量(应在lambda回调结束时销毁),但内存未被释放。
使用Visual Leak Detector (VLD)验证
通过Windows/MSVC广泛使用的内存泄漏检测工具VLD确认了该问题:
- 重复调用availableDevices()时,VLD报告内存泄漏;
- 移除该调用后无泄漏报告,确认泄漏源于Qt的QAudioDeviceInfo实现。
已排查内容
- 预期栈分配的devices列表及QAudioDeviceInfo元素会在每次定时器回调后正确释放;
- 未找到Qt 5.15.18版本关于该特定内存泄漏的相关Bug报告;
- 该问题在多台Windows机器上均可稳定复现。
问题咨询
- Qt 5.15.18 Windows版本中
QAudioDeviceInfo::availableDevices()的内存泄漏是否为已知问题? - 我的代码是否存在内存管理不当等可能导致泄漏的问题?
- 有无可安全获取音频设备信息且无内存泄漏的替代方案?
VLD报告
---------- Block 182 at 0x0000000039725760: 78 bytes ---------- Leak Hash: 0x68333E06, Count: 1, Total 78 bytes Call Stack (TID 31932): ntdll.dll!RtlAllocateHeap() MMDevAPI.DLL!0x00007FF99F45ED72() MMDevAPI.DLL!0x00007FF99F452FE2() wdmaud.drv!0x00007FF9327F4E6C() wdmaud.drv!0x00007FF9327F3298() wdmaud.drv!0x00007FF9327F7610() winmmbase.dll!0x00007FF952AE65DD() winmmbase.dll!0x00007FF952AEFB7F() qtaudio_windowsd.dll!0x00007FF8F5C840E8() qtaudio_windowsd.dll!0x00007FF8F5C83E68() qtaudio_windowsd.dll!0x00007FF8F5C83BDD() D:\B\Q\qtmultimedia\src\multimedia\audio\qaudiodevicefactory.cpp (204): Qt5Multimediad.dll!QAudioDeviceFactory::audioDeviceInfo() + 0x27 bytes D:\B\Q\qtmultimedia\src\multimedia\audio\qaudiodeviceinfo.cpp (68): Qt5Multimediad.dll!QAudioDeviceInfoPrivate::QAudioDeviceInfoPrivate() + 0x23 bytes D:\B\Q\qtmultimedia\src\multimedia\audio\qaudiodeviceinfo.cpp (443): Qt5Multimediad.dll!QAudioDeviceInfo::QAudioDeviceInfo() + 0x3A bytes D:\B\Q\qtmultimedia\src\multimedia\audio\qaudiodevicefactory.cpp (135): Qt5Multimediad.dll!QAudioDeviceFactory::availableDevices() + 0x22 bytes D:\B\Q\qtmultimedia\src\multimedia\audio\qaudiodeviceinfo.cpp (435): Qt5Multimediad.dll!QAudioDeviceInfo::availableDevices() + 0xE bytes D:\Home\Desktop\mm\src\main.cpp (23): app.exe!<lambda_972f05a238b8c048bbd3e638a6c9cd17>::operator()() + 0xD bytes D:\Qt\Qt5.15.18-msvc2022_64\include\QtCore\qobjectdefs_impl.h (146): app.exe!QtPrivate::FunctorCall<QtPrivate::IndexesList<>,QtPrivate::List<>,void,<lambda_972f05a238b8c048bbd3e638a6c9cd17> >::call() + 0xA bytes D:\Qt\Qt5.15.18-msvc2022_64\include\QtCore\qobjectdefs_impl.h (256): app.exe!QtPrivate::Functor<<lambda_972f05a238b8c048bbd3e638a6c9cd17>,0>::call<QtPrivate::List<>,void>() + 0xF bytes D:\Qt\Qt5.15.18-msvc2022_64\include\QtCore\qobjectdefs_impl.h (443): app.exe!QtPrivate::QFunctorSlotObject<<lambda_972f05a238b8c048bbd3e638a6c9cd17>,0,QtPrivate::List<>,void>::impl() + 0x1B bytes D:\B\Q\qtbase\src\corelib\kernel\qobjectdefs_impl.h (398): Qt5Cored.dll!QtPrivate::QSlotObjectBase::call() + 0x42 bytes D:\B\Q\qtbase\src\corelib\kernel\qobject.cpp (3928): Qt5Cored.dll!doActivate<0>() + 0x2F bytes D:\B\Q\qtbase\src\corelib\kernel\qobject.cpp (3988): Qt5Cored.dll!QMetaObject::activate() + 0x13 bytes D:\B\Q\build-msvc\qtbase\src\corelib\.moc\debug\moc_qtimer.cpp (205): Qt5Cored.dll!QTimer::timeout() + 0x19 bytes D:\B\Q\qtbase\src\corelib\kernel\qtimer.cpp (259): Qt5Cored.dll!QTimer::timerEvent() + 0xF bytes D:\B\Q\qtbase\src\corelib\kernel\qobject.cpp (1324): Qt5Cored.dll!QObject::event() + 0x2E bytes D:\B\Q\qtbase\src\widgets\kernel\qapplication.cpp (3640): Qt5Widgetsd.dll!QApplicationPrivate::notify_helper() + 0x1F bytes D:\B\Q\qtbase\src\widgets\kernel\qapplication.cpp (2980): Qt5Widgetsd.dll!QApplication::notify() + 0x1D bytes D:\B\Q\qtbase\src\corelib\kernel\qcoreapplication.cpp (1064): Qt5Cored.dll!QCoreApplication::notifyInternal2() + 0x2E bytes D:\B\Q\qtbase\src\corelib\kernel\qcoreapplication.cpp (1463): Qt5Cored.dll!QCoreApplication::sendEvent() D:\B\Q\qtbase\src\corelib\kernel\qeventdispatcher_win.cpp (432): Qt5Cored.dll!QEventDispatcherWin32Private::sendTimerEvent() + 0x13 bytes D:\B\Q\qtbase\src\corelib\kernel\qeventdispatcher_win.cpp (256): Qt5Cored.dll!qt_internal_proc() + 0x11 bytes USER32.dll!CallWindowProcW() + 0x6A6 bytes USER32.dll!IsWindowUnicode() + 0x3CD bytes D:\B\Q\qtbase\src\corelib\kernel\qeventdispatcher_win.cpp (597): Qt5Cored.dll!QEventDispatcherWin32::processEvents() + 0xB bytes qwindowsd.dll!0x00007FF89FB00024() D:\B\Q\qtbase\src\corelib\kernel\qeventloop.cpp (143): Qt5Cored.dll!QEventLoop::processEvents() D:\B\Q\qtbase\src\corelib\kernel\qeventloop.cpp (235): Qt5Cored.dll!QEventLoop::exec() + 0x41 bytes D:\B\Q\qtbase\src\corelib\kernel\qcoreapplication.cpp (1375): Qt5Cored.dll!QCoreApplication::exec() + 0x22 bytes D:\B\Q\qtbase\src\gui\kernel\qguiapplication.cpp (1871): Qt5Guid.dll!QGuiApplication::exec() D:\B\Q\qtbase\src\widgets\kernel\qapplication.cpp (2833): Qt5Widgetsd.dll!QApplication::exec() D:\Home\Desktop\mm\src\main.cpp (31): app.exe!main() + 0x6 bytes D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl (79): app.exe!invoke_main() D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl (288): app.exe!__scrt_common_main_seh() + 0x5 bytes D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl (331): app.exe!__scrt_common_main() D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp (17): app.exe!mainCRTStartup() KERNEL32.DLL!BaseThreadInitThunk() + 0x17 bytes ntdll.dll!RtlUserThreadStart() + 0x2C bytes Data: 7B 00 32 00 38 00 66 00 62 00 62 00 35 00 34 00 {.2.8.f. b.b.5.4. 31 00 2D 00 66 00 63 00 65 00 65 00 2D 00 34 00 1.-.f.c. e.e.-.4. 30 00 62 00 36 00 2D 00 62 00 34 00 33 00 34 00 0.b.6.-. b.4.3.4. 2D 00 32 00 64 00 31 00 66 00 38 00 30 00 38 00 -.2.d.1. f.8.0.8. 36 00 62 00 64 00 65 00 34 00 7D 00 00 00 6.b.d.e. 4.}..... Visual Leak Detector detected 37 memory leaks (2232 bytes). Largest number used: 11387 bytes. Total allocations: 50233 bytes. Visual Leak Detector is now exiting.
内容的提问来源于stack exchange,提问作者Jim Weiss
相关产品推荐
相关产品推荐

