RTC_DCHECK_IS_ON 时 WebRTC std::deque 迭代器异常
WebRTC std::deque iterator exception when RTC_DCHECK_IS_ON
最近,自从 lib-WebRTC 的 M83 和 M84 版本发布以来,当我在 Windows x64 调试配置 (RTC_DCHECK_IS_ON) 中 运行 我的主机程序时,我遇到了一个奇怪的错误 Visual Studio :
当在 WebRTC 库中创建视频频道时,出现异常
_Deque_const_iterator& operator++() {
#if _ITERATOR_DEBUG_LEVEL != 0
const auto _Mycont = static_cast<const _Mydeque*>(this->_Getcont());
_STL_VERIFY(_Mycont, "cannot increment value-initialized deque iterator");
here----> _STL_VERIFY(this->_Myoff < _Mycont->_Myoff + _Mycont->_Mysize, "cannot increment deque iterator past end");**
#endif // _ITERATOR_DEBUG_LEVEL != 0
++_Myoff;
return *this;
}
因为 _Myoff 为 NULL ...
此 ++ 运算符是从 WebRTC 库中的 rtc_base/thread.cc 调用的:
void ThreadManager::RegisterSendAndCheckForCycles(Thread* source,
Thread* target) {
CritScope cs(&crit_);
std::deque<Thread*> all_targets({target});
// We check the pre-existing who-sends-to-who graph for any path from target
// to source. This loop is guaranteed to terminate because per the send graph
// invariant, there are no cycles in the graph.
for (auto it = all_targets.begin(); it != all_targets.end(); ++it) {
const auto& targets = send_graph_[*it];
all_targets.insert(all_targets.end(), targets.begin(), targets.end());
}
...
它来自 std::deque< rtc::Thread* >
的 ++it
我不太明白可能是什么问题,但迭代器似乎有问题。
也许我在编译的 webrtc.lib 和我的项目之间存在某种配置不匹配,但例如 WebRTC M79 或 M81 没有任何问题。
而且,由于 WebRTC 确实是一个巨大的项目,我不知道从哪里开始调查。
有什么想法吗?
请注意,我也向 WebRTC 团队报告了这个错误:https://bugs.chromium.org/p/webrtc/issues/detail?id=11746
问题出在 rtc_base/thread.cc 文件的 RegisterSendAndCheckForCycles 函数
for (auto it = all_targets.begin(); it != all_targets.end(); ++it) {
const auto& targets = send_graph_[*it];
all_targets.insert(all_targets.end(), targets.begin(), targets.end());
}
当 all_targets.insert 被调用时,“it”变得无效,因为内存分配在 all_targets 中发生了变化,所以下一个 ++it 会产生一个断言失败。使用索引解决问题
这是固定版本:
void ThreadManager::RegisterSendAndCheckForCycles(Thread* source,Thread* target) {
CritScope cs(&crit_);
std::deque<Thread*> all_targets({target});
// We check the pre-existing who-sends-to-who graph for any path from target
// to source. This loop is guaranteed to terminate because per the send graph
// invariant, there are no cycles in the graph.
for (size_t i = 0; i < all_targets.size(); i++) {
const auto& targets = send_graph_[all_targets[i]];
all_targets.insert(all_targets.end(), targets.begin(), targets.end());
}
RTC_CHECK_EQ(absl::c_count(all_targets, source), 0)
<< " send loop between " << source->name() << " and " << target->name();
// We may now insert source -> target without creating a cycle, since there
// was no path from target to source per the prior CHECK.
send_graph_[source].insert(target);
}
我会在几天内直接向 WebRTC 团队提出补丁
这基本上是已接受答案的延续...
如果您遵循 Microsoft 的教程 (https://docs.microsoft.com/en-us/winrtc/getting-started),他们会让您使用 M84 版本(截至 2022 年 5 月发布)。然后,他们告诉您应用他们放在一起的一堆 git 补丁。对于 运行 那些,他们让您首先定义一个名为 WEBRTCM84_ROOT
的环境变量,它是 webrtc\src
目录的绝对路径。如果您没有做所有这些,只需在命令提示符 window 中执行此操作(填写您的实际路径):
set WEBRTCM84_ROOT=C:\abs\path\to\webrtc\src
现在,在某处创建一个git补丁文件,包含以下内容。我只是假设你把它放在直接 adjacent 到 webrtc 存储库的路径上。
ThreadManager.patch
diff --git a/rtc_base/thread.cc b/rtc_base/thread.cc
index 0fb2e813e0..a8cb022fa9 100644
--- a/rtc_base/thread.cc
+++ b/rtc_base/thread.cc
@@ -168,8 +168,8 @@ void ThreadManager::RegisterSendAndCheckForCycles(Thread* source,
// We check the pre-existing who-sends-to-who graph for any path from target
// to source. This loop is guaranteed to terminate because per the send graph
// invariant, there are no cycles in the graph.
- for (auto it = all_targets.begin(); it != all_targets.end(); ++it) {
- const auto& targets = send_graph_[*it];
+ for (size_t i = 0; i < all_targets.size(); i++) {
+ const auto& targets = send_graph_[all_targets[i]];
all_targets.insert(all_targets.end(), targets.begin(), targets.end());
}
RTC_CHECK_EQ(absl::c_count(all_targets, source), 0)
然后,像这样应用它:
pushd "%WEBRTCM84_ROOT%"
git apply "..\..\ThreadManager.patch"
git commit -a -m "Applied ThreadManager patch."
popd
Note: I'm still experiencing some other bad behaviors in debug mode, that aren't present in release, but SamT's solution got me beyond this particular issue.
最近,自从 lib-WebRTC 的 M83 和 M84 版本发布以来,当我在 Windows x64 调试配置 (RTC_DCHECK_IS_ON) 中 运行 我的主机程序时,我遇到了一个奇怪的错误 Visual Studio :
当在 WebRTC 库中创建视频频道时,出现异常
_Deque_const_iterator& operator++() {
#if _ITERATOR_DEBUG_LEVEL != 0
const auto _Mycont = static_cast<const _Mydeque*>(this->_Getcont());
_STL_VERIFY(_Mycont, "cannot increment value-initialized deque iterator");
here----> _STL_VERIFY(this->_Myoff < _Mycont->_Myoff + _Mycont->_Mysize, "cannot increment deque iterator past end");**
#endif // _ITERATOR_DEBUG_LEVEL != 0
++_Myoff;
return *this;
}
因为 _Myoff 为 NULL ...
此 ++ 运算符是从 WebRTC 库中的 rtc_base/thread.cc 调用的:
void ThreadManager::RegisterSendAndCheckForCycles(Thread* source,
Thread* target) {
CritScope cs(&crit_);
std::deque<Thread*> all_targets({target});
// We check the pre-existing who-sends-to-who graph for any path from target
// to source. This loop is guaranteed to terminate because per the send graph
// invariant, there are no cycles in the graph.
for (auto it = all_targets.begin(); it != all_targets.end(); ++it) {
const auto& targets = send_graph_[*it];
all_targets.insert(all_targets.end(), targets.begin(), targets.end());
}
...
它来自 std::deque< rtc::Thread* >
的 ++it我不太明白可能是什么问题,但迭代器似乎有问题。
也许我在编译的 webrtc.lib 和我的项目之间存在某种配置不匹配,但例如 WebRTC M79 或 M81 没有任何问题。 而且,由于 WebRTC 确实是一个巨大的项目,我不知道从哪里开始调查。
有什么想法吗?
请注意,我也向 WebRTC 团队报告了这个错误:https://bugs.chromium.org/p/webrtc/issues/detail?id=11746
问题出在 rtc_base/thread.cc 文件的 RegisterSendAndCheckForCycles 函数
for (auto it = all_targets.begin(); it != all_targets.end(); ++it) {
const auto& targets = send_graph_[*it];
all_targets.insert(all_targets.end(), targets.begin(), targets.end());
}
当 all_targets.insert 被调用时,“it”变得无效,因为内存分配在 all_targets 中发生了变化,所以下一个 ++it 会产生一个断言失败。使用索引解决问题
这是固定版本:
void ThreadManager::RegisterSendAndCheckForCycles(Thread* source,Thread* target) {
CritScope cs(&crit_);
std::deque<Thread*> all_targets({target});
// We check the pre-existing who-sends-to-who graph for any path from target
// to source. This loop is guaranteed to terminate because per the send graph
// invariant, there are no cycles in the graph.
for (size_t i = 0; i < all_targets.size(); i++) {
const auto& targets = send_graph_[all_targets[i]];
all_targets.insert(all_targets.end(), targets.begin(), targets.end());
}
RTC_CHECK_EQ(absl::c_count(all_targets, source), 0)
<< " send loop between " << source->name() << " and " << target->name();
// We may now insert source -> target without creating a cycle, since there
// was no path from target to source per the prior CHECK.
send_graph_[source].insert(target);
}
我会在几天内直接向 WebRTC 团队提出补丁
这基本上是已接受答案的延续...
如果您遵循 Microsoft 的教程 (https://docs.microsoft.com/en-us/winrtc/getting-started),他们会让您使用 M84 版本(截至 2022 年 5 月发布)。然后,他们告诉您应用他们放在一起的一堆 git 补丁。对于 运行 那些,他们让您首先定义一个名为 WEBRTCM84_ROOT
的环境变量,它是 webrtc\src
目录的绝对路径。如果您没有做所有这些,只需在命令提示符 window 中执行此操作(填写您的实际路径):
set WEBRTCM84_ROOT=C:\abs\path\to\webrtc\src
现在,在某处创建一个git补丁文件,包含以下内容。我只是假设你把它放在直接 adjacent 到 webrtc 存储库的路径上。
ThreadManager.patch
diff --git a/rtc_base/thread.cc b/rtc_base/thread.cc
index 0fb2e813e0..a8cb022fa9 100644
--- a/rtc_base/thread.cc
+++ b/rtc_base/thread.cc
@@ -168,8 +168,8 @@ void ThreadManager::RegisterSendAndCheckForCycles(Thread* source,
// We check the pre-existing who-sends-to-who graph for any path from target
// to source. This loop is guaranteed to terminate because per the send graph
// invariant, there are no cycles in the graph.
- for (auto it = all_targets.begin(); it != all_targets.end(); ++it) {
- const auto& targets = send_graph_[*it];
+ for (size_t i = 0; i < all_targets.size(); i++) {
+ const auto& targets = send_graph_[all_targets[i]];
all_targets.insert(all_targets.end(), targets.begin(), targets.end());
}
RTC_CHECK_EQ(absl::c_count(all_targets, source), 0)
然后,像这样应用它:
pushd "%WEBRTCM84_ROOT%"
git apply "..\..\ThreadManager.patch"
git commit -a -m "Applied ThreadManager patch."
popd
Note: I'm still experiencing some other bad behaviors in debug mode, that aren't present in release, but SamT's solution got me beyond this particular issue.