本机 WebRTC 在 webrtc::PeerConnectionInterface::RTCConfiguration 析构函数中崩溃
Native WebRTC crashes in webrtc::PeerConnectionInterface::RTCConfiguration destructor
我正在用 C++ 编写 WebRTC 客户端。它需要跨平台工作。我从 Windows 上的 POC 开始。我可以连接和断开 to/from 示例 peerconnection_server.exe。
根据 Microsoft“入门”教程 (https://docs.microsoft.com/en-us/winrtc/getting-started),我使用的是 WebRTC“M84”版本。
我知道这个类似的 SO post,但这不是同一个问题,所以请不要指出我:
这是 Linux 上的构造函数问题。我的问题是 Windows 上的析构函数...(显然 class 总的来说肯定有缺陷..)
言归正传,我发现我永远无法销毁 webrtc::PeerConnectionInterface::RTCConfiguration
对象。如果我这样做,则会产生一个致命错误,说明应用程序以某种非法方式写入堆。我如何或何时使用 class 没有区别——它总是在破坏时爆炸。所有需要做的测试如下:
webrtc::PeerConnectionInterface::RTCConfiguration *config
= new webrtc::PeerConnectionInterface::RTCConfiguration();
delete config;
在 delete
线上 - kaboom!
我找到了使用此配置 class 的各种示例。没有人看起来有任何此类问题,并且似乎没有跳过箍来处理这个问题。通常,这些对象之一是在 PeerConnection 存在时创建的,然后只允许超出本地函数的范围。考虑到它是一个“配置”对象,它应该是相当良性的——但显然不是!
这里有什么秘诀?
查看源代码,默认构造函数和析构函数的定义非常简单。那么,是不是配置中某个成员对象的bug?
PeerConnectionInterface::RTCConfiguration::RTCConfiguration() = default;
...
PeerConnectionInterface::RTCConfiguration::~RTCConfiguration() = default;
事实证明,这不仅特定于 Windows/MSVC,而且特定于 DEBUG 模式。在发布模式下,这不会发生在我身上。显然,这是由于 link 年龄不匹配造成的。如果您使用给定的 /MDd
或 /MT
开关等进行编译,如果您 link 到其他不同意的库或 dll,您将 运行 陷入此类问题那个细节。 (然而,值得注意的是,我还没有在我的构建中看到任何其他此类问题 - 只有这个析构函数行为不端。奇怪!)让 WebRTC 在 Windows 中构建需要各种 linkage 到 Windows SDK和系统库。至少其中一个必须与我不匹配。因此,这是解决方法 - 自动 忽略 错误!
首先,为了方便起见,设置一个#define来标识条件场景。我正在使用 Qt,所以对我来说看起来像这样:
#if defined(QT_DEBUG) && defined(Q_CC_MSVC)
#define MSVC_DEBUG
#endif
然后,包括这个 Windows api header:
#ifdef MSVC_DEBUG
#include <crtdbg.h>
#endif
我正在通过 std::unique_ptr 管理我的配置 object(在此 .cpp 中使用 STL 而不是 Qt,因为 WebRTC 当然不使用 Qt,而且使用“在罗马时……”方法):
std::unique_ptr<webrtc::PeerConnectionInterface::RTCConfiguration> connConfig_;
最后,当我想销毁这个 object 时,我调用了一个类似如下的函数:
// Note: in Windows debug mode this destructor produces a heap assertion
// failure, which would create an ugly popup if not for the explicit
// suppression code surrounding the reset() below
void SomeClass::destroyConnectionConfig()
{
if( !connConfig_.get() ) return;
#ifdef MSVC_DEBUG
// Temporarily disabled popup error messages on Windows
auto warnCrtMode( _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE ) );
auto warnCrtFile( _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR ) );
auto errorCrtMode( _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE ) );
auto errorCrtFile( _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDERR ) );
auto assertCrtMode( _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE ) );
auto assertCrtFile( _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR ) );
auto errorMode( _set_error_mode( _OUT_TO_STDERR ) );
#endif
connConfig_.reset();
#ifdef MSVC_DEBUG
// Restore error handling setttings
_CrtSetReportMode( _CRT_WARN, warnCrtMode );
_CrtSetReportFile( _CRT_WARN, warnCrtFile );
_CrtSetReportMode( _CRT_ERROR, errorCrtMode );
_CrtSetReportFile( _CRT_ERROR, errorCrtFile );
_CrtSetReportMode( _CRT_ASSERT, assertCrtMode );
_CrtSetReportFile( _CRT_ASSERT, assertCrtFile );
_set_error_mode( errorMode );
#endif
}
我正在用 C++ 编写 WebRTC 客户端。它需要跨平台工作。我从 Windows 上的 POC 开始。我可以连接和断开 to/from 示例 peerconnection_server.exe。
根据 Microsoft“入门”教程 (https://docs.microsoft.com/en-us/winrtc/getting-started),我使用的是 WebRTC“M84”版本。
我知道这个类似的 SO post,但这不是同一个问题,所以请不要指出我:
言归正传,我发现我永远无法销毁 webrtc::PeerConnectionInterface::RTCConfiguration
对象。如果我这样做,则会产生一个致命错误,说明应用程序以某种非法方式写入堆。我如何或何时使用 class 没有区别——它总是在破坏时爆炸。所有需要做的测试如下:
webrtc::PeerConnectionInterface::RTCConfiguration *config
= new webrtc::PeerConnectionInterface::RTCConfiguration();
delete config;
在 delete
线上 - kaboom!
我找到了使用此配置 class 的各种示例。没有人看起来有任何此类问题,并且似乎没有跳过箍来处理这个问题。通常,这些对象之一是在 PeerConnection 存在时创建的,然后只允许超出本地函数的范围。考虑到它是一个“配置”对象,它应该是相当良性的——但显然不是!
这里有什么秘诀?
查看源代码,默认构造函数和析构函数的定义非常简单。那么,是不是配置中某个成员对象的bug?
PeerConnectionInterface::RTCConfiguration::RTCConfiguration() = default;
...
PeerConnectionInterface::RTCConfiguration::~RTCConfiguration() = default;
事实证明,这不仅特定于 Windows/MSVC,而且特定于 DEBUG 模式。在发布模式下,这不会发生在我身上。显然,这是由于 link 年龄不匹配造成的。如果您使用给定的 /MDd
或 /MT
开关等进行编译,如果您 link 到其他不同意的库或 dll,您将 运行 陷入此类问题那个细节。 (然而,值得注意的是,我还没有在我的构建中看到任何其他此类问题 - 只有这个析构函数行为不端。奇怪!)让 WebRTC 在 Windows 中构建需要各种 linkage 到 Windows SDK和系统库。至少其中一个必须与我不匹配。因此,这是解决方法 - 自动 忽略 错误!
首先,为了方便起见,设置一个#define来标识条件场景。我正在使用 Qt,所以对我来说看起来像这样:
#if defined(QT_DEBUG) && defined(Q_CC_MSVC)
#define MSVC_DEBUG
#endif
然后,包括这个 Windows api header:
#ifdef MSVC_DEBUG
#include <crtdbg.h>
#endif
我正在通过 std::unique_ptr 管理我的配置 object(在此 .cpp 中使用 STL 而不是 Qt,因为 WebRTC 当然不使用 Qt,而且使用“在罗马时……”方法):
std::unique_ptr<webrtc::PeerConnectionInterface::RTCConfiguration> connConfig_;
最后,当我想销毁这个 object 时,我调用了一个类似如下的函数:
// Note: in Windows debug mode this destructor produces a heap assertion
// failure, which would create an ugly popup if not for the explicit
// suppression code surrounding the reset() below
void SomeClass::destroyConnectionConfig()
{
if( !connConfig_.get() ) return;
#ifdef MSVC_DEBUG
// Temporarily disabled popup error messages on Windows
auto warnCrtMode( _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE ) );
auto warnCrtFile( _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR ) );
auto errorCrtMode( _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE ) );
auto errorCrtFile( _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDERR ) );
auto assertCrtMode( _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE ) );
auto assertCrtFile( _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR ) );
auto errorMode( _set_error_mode( _OUT_TO_STDERR ) );
#endif
connConfig_.reset();
#ifdef MSVC_DEBUG
// Restore error handling setttings
_CrtSetReportMode( _CRT_WARN, warnCrtMode );
_CrtSetReportFile( _CRT_WARN, warnCrtFile );
_CrtSetReportMode( _CRT_ERROR, errorCrtMode );
_CrtSetReportFile( _CRT_ERROR, errorCrtFile );
_CrtSetReportMode( _CRT_ASSERT, assertCrtMode );
_CrtSetReportFile( _CRT_ASSERT, assertCrtFile );
_set_error_mode( errorMode );
#endif
}