1

由于某种原因,一旦我引用第三方供应商的 dll 类,集成调试器就会导致错误。相同的代码在构建并作为发行版运行时运行,独立运行。调试和发布的两个属性应该是相同的,因为我没有真正改变它们。我将 lib 文件添加到两个构建的路径中。我只是有:

ClassNameFromDll blah;

当它到达这里时,我得到了这个异常:

MTGO SO Bot.exe 中 0x78a3f623 (mfc90ud.dll) 处的未处理异常:0xC0000005:访问冲突读取位置 0xf78e4568。

它出现在:afxtls.cpp,第 252 行。

这是一个 MFC 应用程序,但我并没有真正使用任何 MFC,除了一个非常简单的 gui,它触发了一个全是 win32 的事件。我正在使用 Visual Studio 2008 Express。

4

3 回答 3

2

查看我的 VC9 安装中的 atltls.cpp 文件,崩溃发生在这里:

inline void* CThreadSlotData::GetThreadValue(int nSlot)
{
    EnterCriticalSection(&m_sect);
    ASSERT(nSlot != 0 && nSlot < m_nMax);
    ASSERT(m_pSlotData != NULL);
    ASSERT(m_pSlotData[nSlot].dwFlags & SLOT_USED);   // <== crash
    // ...
}

因此,在发布版本中没有发生崩溃的原因是因为 ASSERT() 在该版本中是无操作的。我不熟悉 ATL 对线程本地存储的使用,但这个断言表明某些东西正在请求一个尚未存储任何内容的插槽中的值。

那个 TLS 插槽的初始化是你的责任还是第 3 方 DLL 的责任,我不知道。

它看起来GetThreadValue()有一些额外的保护措施,例如它会在发布版本中为未初始化的插槽返回一个 NULL 指针(尽管我不确定这是否会得到保证) - 我敢打赌,第 3 方 DLL 依赖于那个行为(即,它检查是否返回 NULL),因此在发布版本中不会发生崩溃。请注意,供应商可能会间接使用 CThreadSlotData 类(堆栈跟踪会提供有关此的线索),因此他们可能不知道它的期望。

于 2009-02-05T16:41:12.460 回答
1

引人入胜的心理调试

它在发布模式下运行良好并在调试模式下崩溃的事实让我相信你已经设法以某种方式引用了该 DLL (mfc90u.dll) 的发布版本,而不是引用库本身并允许链接器来决定要导入哪个版本。

您可能没有在此应用程序中将 MFC 用于任何东西,但如果它是作为 MFC 应用程序构建的,无论您是否需要,您都将获得所有 MFC 内容(这意味着您还必须解决 MFC 依赖问题并发布MFC DLL 与您的应用程序)。

于 2009-02-05T15:45:19.637 回答
0

你有可以发布的堆栈跟踪吗?它可能有一些有用的信息。

如果供应商仍然积极支持 3rd 方 DLL,那么您应该做的第一件事是查看是否可以使用一个非常简单的程序出现同样的问题,您可以将其发送给供应商并要求他们修复它。

如果供应商不可用或响应不够:

如果您有第 3 方 DLL 的源代码并且可以轻松构建您自己的版本,那么您可能拥有最好的调试方法(没有让供应商支持您)。即使您无法轻松构建可调试源代码的 DLL,您也可以追溯构造函数的汇编指令并将源代码用作映射来帮助您了解正在发生的事情。

即使您没有第 3 方 DLL 的源代码,那么我认为最好的做法是通过构造函数进行跟踪ClassNameFromDll以尝试找出问题所在。比较 Debug 版本与 Release 版本中的指令路径可能会有所帮助。

MFC 源代码与 MSVC 一起分发(可能不与 Express 版本一起分发,但我认为与所有其他版本一起分发)所以当您进入 MFC DLL 的代码时,您可能会发现该源代码有助于弄清楚发生了什么。

于 2009-02-05T16:21:43.887 回答