c++ - 函数从同一个线程调用两次,用于同一个对象,调用栈相同
问题描述
背景
我正在调试一个我愿意加入并学习 C++ 的开源项目。然后我尝试扩展其中一个问题所需的一些功能,我偶然发现了一个有趣的案例(在我的生活中从未见过这样的事情)。
源代码
QuestSet Player::GetQuestForEvent(uint16 eventId) const
{
QuestSet eventQuests; // QuestSet is typedef for std::set<uint32>
for (uint8 i = 0; i < MAX_QUEST_LOG_SIZE; ++i)
{
uint32 questId = GetQuestSlotQuestId(i);
if (questId == 0)
continue;
QuestStatusMap::const_iterator qs_itr = m_QuestStatus.find(questId);
if (qs_itr == m_QuestStatus.end())
continue;
QuestStatusData const& qs = qs_itr->second;
Quest const* qinfo = sObjectMgr->GetQuestTemplate(questId);
if (!qinfo)
continue;
if (qinfo->GetEventIdForQuest() == eventId)
eventQuests.insert(questId);
}
return eventQuests; <--- breakpoint here
}
我注意到我的服务器崩溃了
worldserver.exe 中 0x00007FFE1BE6A388 (KernelBase.dll) 处未处理的异常:0xC0000005:访问冲突。
然后是我服务器上的这个日志
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.20.27508\include\xtree(240) :断言失败:范围内的映射/设置迭代器来自不同的容器
所以我在前面提到的地方放了断点,我注意到这个函数被调用了两次。我知道上传图片可能不是最好的选择,但我认为在这种情况下它是最好的解释,所以看看。
截图
这是项目中唯一调用此函数的地方。
void OnLogin(Player* player, bool /*firstLogin*/) override
{
QuestSet eventQuests = player->GetQuestForEvent(1);
/*std::for_each(eventQuests.begin(), eventQuests.end(), [&player](uint32 questId)
{
player->AbandonQuest(questId);
});*/
}
我知道这听起来很傻,但我没有建议,请你指出我正确的方向,理解为什么这个断点被击中两次最有可能也可以解决异常。
故障排除:
- 项目是在 Debug 配置中构建的
- 调用堆栈,线程和
this
对象通过两次命中都是相同的。
解决方案
很可能该函数实际上并未被调用两次。您只是从两次击中相同的断点得出错误的结论。
Visual Studio 允许您检查断点附近的汇编代码,Ctrl+Alt+D
我相信默认是。在那里,您将看到混合的汇编指令(您的 CPU 实际执行的操作)和“以下指令源自哪一行代码”的调试信息。
我希望您会看到该return eventQuests;
行与两个汇编指令块相关联,中间还有另一个指令块。您将首先在第一组指令中命中断点,然后执行第二组指令(例如关联到循环或右括号),然后由于第二组指令再次命中断点。是的,这听起来很愚蠢,但 MSVC 输出的调试信息并不是我见过的最好的。
另一种简单的检查方法是std::cout << "Hi" << std::endl
在返回之前插入一个打印语句(如 ),并检查您是否得到一个或两个打印输出。除非您得到两个打印输出,否则您多次实际输入该函数的结论是错误的。
推荐阅读
- python - 在上传到谷歌云存储 django 之前调整图像大小
- c# - 如何生成超过 1048576 行的 Excel 工作表
- c# - 如何对 Core MVC 控制器操作是否调用 ControllerBase.Problem() 进行单元测试
- android - SOFT_INPUT_MODE_CHANGED 是做什么的?
- sql - .get() 在 Django 的底层是如何工作的?
- ios - 为什么我在 iOS 上执行屏幕锁定测试时我的应用程序会关闭?
- c++ - 我的基本零初始化代码有问题吗?
- r - 根据性别分布简单调整付款,轻松修复?
- java - Android 服务 TextToSpeech
- javascript - 使用 WEBGL 构建 3D 形状时,JS 数组是否有限制?