应用程序验证工具 - 停止代码 - 基础知识
这组基本测试包含以下停止代码。
异常停止详细信息
尝试在不可执行内存中执行代码(第一次机会)。
可能的原因如果应用程序尝试从一个不可执行或空闲的地址运行代码,则会生成此停止。 要调试此停止:$ u parameter2 - 用于反汇编原因代码;$ .exr parameter3 - 用于显示异常信息;$ .cxr parameter4 后跟 kb - 用于显示异常上下文信息和异常发生时的堆栈跟踪。
应用程序验证程序显示的信息- 参数 1 - 正在访问的地址。
- 参数 2 - 执行无效访问的代码。
- 参数 3 - 异常记录。 使用 .exr 显示它。
- 参数 4 - 上下文记录。 使用 .cxr 显示它。
- 测试层: 异常
- 停止 ID: FIRST_CHANCE_ACCESS_VIOLATION_CODE
- 停止代码: 650NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
句柄停止详细信息
当前堆栈跟踪的无效句柄异常。
可能的原因如果堆栈顶层的函数向系统例程传递了一个无效句柄,则会生成此停止。 通常,一个简单的 kb 命令就能显示所传递句柄的值(必须是参数之一,通常是第一个)。 如果值为 null,那么这显然是错误的。 如果该值看起来正常,则需要使用 !htrace 调试器扩展来获取与该句柄值相关的操作历史记录。 在大多数情况下,必须在关闭后使用句柄值。
应用程序验证程序显示的信息- 参数 1 - 异常代码。
- 参数 2 - 异常记录。 使用 .exr 显示它。
- 参数 3 - 上下文记录。 使用 .cxr 显示它。
- 参数 4 - 未使用。
- 测试层: 句柄
- 停止 ID: INVALID_HANDLE
- 停止代码: 300NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
当前堆栈跟踪使用的 TLS 索引无效。
可能的原因如果堆栈顶层的函数向 TLS 系统例程传递了无效的 TLS 索引,则会生成此停止。 通常,一个简单的 kb 命令就能发现问题所在。 这里的典型错误是假定 TLS 索引为某个值,而不是调用 TlsAlloc。 出现这种情况的原因可能是认为总是会得到值 N,因此没有必要调用 TlsAlloc,或者更常见的原因是变量未初始化。
应用程序验证程序显示的信息- 参数 1 - 无效 TLS 索引。
- 参数 2 - 预期索引的下半部分。
- 参数 3 - 未使用。
- 参数 4 - 未使用。
- 测试层: 句柄
- 停止 ID: INVALID_TLS_VALUE
- 停止代码: 300NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
WaitForMultipleObjects 调用的参数无效。
可能的原因如果堆栈顶层的函数在调用 WaitForMultipleObjects 时将等待的句柄数组地址设为 NULL 或句柄数设为 0,则会生成此停止。 一个简单的 kb 命令就能显示错误调用该 API 的函数。
应用程序验证程序显示的信息- 参数 1 - 对象句柄向量的地址。
- 参数 2 - 句柄数量。
- 参数 3 - 未使用。
- 参数 4 - 未使用。
- 测试层: 句柄
- 停止 ID: INCORRECT_WAIT_CALL
- 停止代码: 300NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
作为参数传递的 NULL 句柄。 必须使用有效的句柄。
可能的原因如果堆栈顶层的函数向系统例程传递了一个 NULL 句柄,则会生成此停止。
应用程序验证程序显示的信息- 参数 1 - 未使用。
- 参数 2 - 未使用。
- 参数 3 - 未使用。
- 参数 4 - 未使用。
- 测试层: 句柄
- 停止 ID: NULL_HANDLE
- 停止代码: 300NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
正在等待 DllMain 中的线程句柄。
可能的原因如果当前线程正在当前进程中加载的某个 DLL 的 DllMain 函数内运行代码,并且调用了 WaitForSingleObjects 或 WaitForMultipleObjects 以等待同一进程中的线程句柄,则会生成此停止。 这很可能导致死锁,因为除非第二个线程退出,否则线程句柄不会收到信号。 当第二个线程调用 ExitThread 时,它会尝试获取 DLL 加载程序锁,然后为当前进程中的所有 DLL 调用 DllMain (DLL_THREAD_DETACH)。 但是加载程序锁是由第一个线程(等待线程句柄的线程)拥有的,因此两个线程会死锁。
应用程序验证程序显示的信息- 参数 1 - 线程句柄。
- 参数 2 - 未使用。
- 参数 3 - 未使用。
- 参数 4 - 未使用。
- 测试层: 句柄
- 停止 ID: WAIT_IN_DLLMAIN
- 停止代码: 300NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
句柄的对象类型不正确。
可能的原因如果当前线程使用对象类型不正确的对象句柄调用 API,则会生成此停止。 例如,以一个 Semaphore 句柄作为参数调用 SetEvent 时,则会生成此停止。 要调试此停止:$ kb - 显示当前堆栈跟踪。 原因可能是调用 verifier.dll 的 DLL;$ du parameter2 - 用于显示句柄的实际类型。 句柄值为 parameter1。 在上面的示例中,将显示:Semaphore。 $ du parameter3 - 显示 API 期望的对象类型。 在上面的示例中,此名称将是:Event。 htrace parameter1 可能会有帮助,因为它会显示最近对该句柄进行的打开/关闭操作的堆栈跟踪。
应用程序验证程序显示的信息- 参数 1 - 句柄值。
- 参数 2 - 对象类型名称。 使用 du 来显示它
- 参数 3 - 预期对象类型名称。 使用 du 来显示它
- 参数 4 - 未使用。
- 测试层: 句柄
- 停止 ID: INCORRECT_OBJECT_TYPE
- 停止代码: 300NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
堆停止详细信息
未知错误。
可能的原因如果遇到的错误无法以任何其他方式分类,则会出现此信息。 目前尚未使用。
应用程序验证程序显示的信息- 参数 1 - 未使用
- 参数 2 - 未使用
- 参数 3 - 未使用
- 参数 4 - 未使用
- 测试层: 堆
- 停止 ID: UNKNOWN_ERROR
- 停止代码: 0NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
访问冲突异常。
可能的原因这是最常见的应用程序验证工具停止功能。 通常是由缓冲区溢出错误引起的。 堆验证工具会在堆分配的末尾放置一个不可访问的页面,缓冲区溢出会因触及该页面而导致异常。 要调试此停止,需要识别导致异常的访问地址,然后使用以下调试器命令:!heap -p -a ACCESS_ADDRESS,此命令将详细说明错误的性质以及是哪个堆块溢出。 它还会给出块分配的堆栈跟踪。 导致停机的原因还有很多。 例如,在释放后访问堆块。 同样的调试器命令在这种情况下也很有用。
应用程序验证程序显示的信息- 参数 1 - 导致异常的无效地址
- 参数 2 - 执行无效访问的代码地址
- 参数 3 - 异常记录
- 参数 4 - 上下文记录
- 测试层: 堆
- 停止 ID: ACCESS_VIOLATION
- 停止代码: 0NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
在使用 HEAP_NO_SERIALIZE 标志创建的堆中进行多线程访问。
可能的原因使用 HEAP_NO_SERIALIZE 标志创建的堆不允许两个线程同时访问。 如果检测到此类情况,则会收到此消息。 这种情况通常通过链接到 C 运行时的单线程版本来进入程序。 例如,如果使用了适当的标志,Visual C++ 就可以静态链接此类库。 然后,人们就会忘记这一细节并使用多线程。 此错误在现实中很难调试,因为它会显示为神秘的数据损坏。
应用程序验证程序显示的信息- 参数 1 - 发生操作的堆。
- 参数 2 - 堆关键部分当前所有者的线程 ID。
- 参数 3 - 尝试进入堆的当前线程 ID。
- 参数 4 - 未使用
- 测试层: 堆
- 停止 ID: UNSYNCHRONIZED_ACCESS
- 停止代码: 0NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
极端大小请求。
可能的原因如果在 HeapAlloc() 或 HeapReAlloc() 操作中,块的大小超过了任何合理的值,就会生成此消息。 在 32 位平台上,该值通常为 0x80000000,而在 64 位平台上则要大得多。
应用程序验证程序显示的信息- 参数 1 - 发生操作的堆。
- 参数 2 - 要求的大小
- 参数 3 - 未使用
- 参数 4 - 未使用
- 测试层: 堆
- 停止 ID: EXTREME_SIZE_REQUEST
- 停止代码: 0NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
签名不正确的堆句柄。
可能的原因堆结构会用一个 magic 值进行标记。 如果在调用堆接口时使用的堆句柄不具有此模式,则会生成此停止。 如果内部堆结构出现某种损坏(随机损坏),或者只是使用了一个假值作为堆句柄,就会出现此错误。 要获取有效堆句柄值列表,请使用以下调试器命令:!heap -p。请注意,如果只是在堆操作中将一个有效的堆句柄与另一个有效的堆句柄进行切换,则不会获得此停止(毕竟句柄似乎是有效的)。 然而,堆验证程序会检测到这种情况,并报告 SWITCHED_HEAP_HANDLE 停止。
应用程序验证程序显示的信息- 参数 1 - 调用堆接口时使用的堆句柄
- 参数 2 - 未使用
- 参数 3 - 未使用
- 参数 4 - 未使用
- 测试层: 堆
- 停止 ID: BAD_HEAP_HANDLE
- 停止代码: 0NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
堆指针损坏或使用了错误的堆。
可能的原因通常,如果块在一个堆中分配,而在另一个堆中释放,就会发生这种情况。 使用 !heap -p 命令获取所有有效堆句柄值的列表。 最常见的示例是使用 malloc() 进行 msvcrt 分配,然后使用 HeapFree() 进行 kernel32 解除分配。
应用程序验证程序显示的信息- 参数 1 - 调用中使用的堆句柄。
- 参数 2 - 操作中涉及的堆块。
- 参数 3 - 堆块的大小。
- 参数 4 - 最初分配块的堆。
- 测试层: 堆
- 停止 ID: SWITCHED_HEAP_HANDLE
- 停止代码: 0NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
已释放堆块。
可能的原因如果块被释放两次,就会出现这种情况。 释放的块会以特殊方式进行标记,并在延迟释放队列中保留一段时间。 如果有错误的程序尝试再次释放该块,假定该块没有从延迟释放队列中取消排队,也没有将其内存重新用于其他分配,那么该块就会被捕获。 无延迟队列的深度约为数千个块,因此很有可能捕捉到大多数重复释放。
应用程序验证程序显示的信息- 参数 1 - 拥有块的堆句柄。
- 参数 2 - 再次释放堆块。
- 参数 3 - 堆块的大小。
- 参数 4 - 未使用
- 测试层: 堆
- 停止 ID: DOUBLE_FREE
- 停止代码: 0NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
损坏的堆块。
可能的原因如果无法将堆块中的损坏归入更具体的类别,则会出现这种一般错误。
应用程序验证程序显示的信息- 参数 1 - 调用中使用的堆句柄。
- 参数 2 - 操作中涉及的堆块。
- 参数 3 - 堆块的大小。
- 参数 4 - 已保留
- 测试层: 堆
- 停止 ID: CORRUPTED_HEAP_BLOCK
- 停止代码: 0NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
尝试销毁进程堆。
可能的原因尝试销毁默认进程堆(GetProcessHeap() 接口返回的进程堆)是错误的。
应用程序验证程序显示的信息- 参数 1 - 与 HeapDestroy 一起使用的堆句柄。
- 参数 2 - 未使用
- 参数 3 - 未使用
- 参数 4 - 未使用
- 测试层: 堆
- 停止 ID: DESTROY_PROCESS_HEAP
- 停止代码: 0NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
执行堆管理代码时出现意外异常。
可能的原因如果在执行堆管理器代码时在非法情况下出现访问冲突,则会生成此停止。 在极少数情况下可以这样做,例如调用 HeapValidate() 或 HeapSize() 时。 异常记录信息(第三个参数)可用于查找异常的确切上下文。 为此,请使用以下调试器命令:$ .exr STOP-PARAMETER-2 $ .cxr STOP-PARAMETER-3。通常,如果内部堆结构出现随机损坏,就会出现这种停止。
应用程序验证程序显示的信息- 参数 1 - 操作涉及的堆。
- 参数 2 - 异常记录。
- 参数 3 - 上下文记录。
- 参数 4 - 异常代码(C0000005 - 访问冲突)
- 测试层: 堆
- 停止 ID: UNEXPECTED_EXCEPTION
- 停止代码: 0NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
验证堆块标头时出现的异常。
可能的原因如果我们确实无法确定区块的任何特定损坏类型,就会出现这种情况。 当传递给堆释放的堆块地址指向不可访问的内存区域(损坏的指针、未初始化的指针等)时,很可能就会出现这种停止。
应用程序验证程序显示的信息- 参数 1 - 拥有块的堆句柄。
- 参数 2 - 已损坏的堆块。
- 参数 3 - 数据块的大小,如果无法确定大小,则为零。
- 参数 4 - 未使用。
- 测试层: 堆
- 停止 ID: CORRUPTED_HEAP_BLOCK_EXCEPTION_RAISED_FOR_HEADER
- 停止代码: 0NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
验证堆块时出现的异常。
可能的原因如果我们确实无法确定区块的任何特定损坏类型,就会出现这种情况。 例如,如果在堆释放操作过程中传递指向不可访问内存区域的地址,就会出现这种情况。 如果未在全页堆块中找到该块,而是将其作为轻型页堆块进行探测,则也会出现双重释放的情况。
应用程序验证程序显示的信息- 参数 1 - 调用中使用的堆句柄。
- 参数 2 - 操作中涉及的堆块。
- 参数 3 - 堆块的大小。
- 参数 4 - 已保留。
- 测试层: 堆
- 停止 ID: CORRUPTED_HEAP_BLOCK_EXCEPTION_RAISED_FOR_PROBING
- 停止代码: 0NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
堆块在被释放后发生损坏。
可能的原因如果内存块被释放后又被写入,就会出现这种情况。
应用程序验证程序显示的信息- 参数 1 - 拥有块的堆句柄。
- 参数 2 - 已损坏的堆块。
- 参数 3 - 数据块的大小,如果无法确定大小,则为零。
- 参数 4 - 未使用。
- 测试层: 堆
- 停止 ID: CORRUPTED_HEAP_BLOCK_HEADER
- 停止代码: 0NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
已释放堆数据块的中缀模式已损坏。
可能的原因释放的块有时会被标记为不可访问,程序触碰它们就会违反访问规则(不同的验证程序停止)。 在其他情况下(轻型页堆块),块会被标记为 magic 模式并被保留一段时间。 最终以先进先出的方式真正释放区块。 此时会检查中缀模式,如果它已被修改,则就会出现中断。 中断时刻的堆栈无关紧要。 需要弄清代码块的性质,并对可能出错的代码进行代码审查。
应用程序验证程序显示的信息- 参数 1 - 拥有块的堆句柄。
- 参数 2 - 正在释放的堆块。
- 参数 3 - 堆块的大小。
- 参数 4 - 已保留。
- 测试层: 堆
- 停止 ID: CORRUPTED_FREED_HEAP_BLOCK
- 停止代码: 0NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
堆块的后缀模式已损坏。
可能的原因最典型的情况是缓冲区溢出错误。 有时,应用程序验证程序会在分配结束时放置不可访问的页面,缓冲区溢出限会导致访问冲突,有时堆块后面会出现一个 magic 模式。 如果在释放区块时改变了此模式,就会出现此中断。 这些中断可能很难调试,因为不知道发生损坏的实际时间。 只需访问释放时间(发生停止的时间)和分配堆栈跟踪 (!heap -p -a HEAP_ADDRESS)
应用程序验证程序显示的信息- 参数 1 - 调用中使用的堆句柄。
- 参数 2 - 操作中涉及的堆块。
- 参数 3 - 堆块的大小。
- 参数 4 - 已保留。
- 测试层: 堆
- 停止 ID: CORRUPTED_HEAP_BLOCK_SUFFIX
- 停止代码: 0NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
堆块的起始戳记已损坏。
可能的原因缓冲区不足时会出现这种情况。
应用程序验证程序显示的信息- 参数 1 - 调用中使用的堆句柄。
- 参数 2 - 操作中涉及的堆块。
- 参数 3 - 堆块的大小。
- 参数 4 - 损坏的戳记值。
- 测试层: 堆
- 停止 ID: CORRUPTED_HEAP_BLOCK_START_STAMP
- 停止代码: 0NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
堆块的结束戳记已损坏。
可能的原因缓冲区不足时会出现这种情况。
应用程序验证程序显示的信息- 参数 1 - 调用中使用的堆句柄。
- 参数 2 - 操作中涉及的堆块。
- 参数 3 - 堆块的大小。
- 参数 4 - 损坏的戳记值。
- 测试层: 堆
- 停止 ID: CORRUPTED_HEAP_BLOCK_END_STAMP
- 停止代码: 0NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
堆块的前缀模式已损坏。
可能的原因缓冲区不足时会出现这种情况。
应用程序验证程序显示的信息- 参数 1 - 调用中使用的堆句柄。
- 参数 2 - 操作中涉及的堆块。
- 参数 3 - 堆块的大小。
- 参数 4 - 已保留。
- 测试层: 堆
- 停止 ID: CORRUPTED_HEAP_BLOCK_PREFIX
- 停止代码: 0NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
当前堆栈跟踪的首次访问冲突。
可能的原因这是最常见的应用程序验证工具停止功能。 通常是由缓冲区溢出错误引起的。 堆验证工具会在堆分配的末尾放置一个不可访问的页面,缓冲区溢出会因触及该页面而导致异常。 要调试此停止,需要识别导致异常的访问地址,然后使用以下调试器命令:!heap -p -a ACCESS_ADDRESS,此命令将详细说明错误的性质以及是哪个堆块溢出。 它还会给出块分配的堆栈跟踪。 导致停机的原因还有很多。 例如,在释放后访问堆块。 同样的调试器命令在这种情况下也很有用。
应用程序验证程序显示的信息- 参数 1 - 导致异常的无效地址。
- 参数 2 - 执行无效访问的代码地址。
- 参数 3 - 异常记录。
- 参数 4 - 上下文记录。
- 测试层: 堆
- 停止 ID: FIRST_CHANCE_ACCESS_VIOLATION
- 停止代码: 0NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
进程堆列表计数无效。
可能的原因如果页面堆管理器在调用 GetProcessHeaps 时检测到某些内部不一致,则会出现此消息。 这可能是进程空间中的一些随机损坏造成的。
应用程序验证程序显示的信息- 参数 1 - 实际堆计数。
- 参数 2 - 页堆计数。
- 参数 3 - 未使用
- 参数 4 - 未使用
- 测试层: 堆
- 停止 ID: CORRUPTED_HEAP_LIST
- 停止代码: 0NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
泄露停止详细信息
堆分配已泄露。
可能的原因如果分配的所有者 dll 在拥有资源时被动态卸载,则会生成此停止。
应用程序验证程序显示的信息- 参数 1 - 已泄露分配的地址。 运行 !heap -p -a <地址>以获取有关分配的其他信息。
- 参数 2 - 到分配堆栈跟踪的地址。 运行 dps <地址>以查看分配堆栈。
- 参数 3 - 所有者地址 dll 名称。 运行 du <地址>以读取 dll 名称。
- 参数 4 - 所有者 dll 的基础。 运行 .reload <dll_name> = <地址>以重新加载所有者 dll。 使用“lm”获取更多已加载和未加载模块的相关信息。
- 测试层: 泄露
- 停止 ID: ALLOCATION
- 停止代码: 900NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
一个 HANDLE 被泄露。
可能的原因如果句柄的所有者 dll 在拥有资源时被动态卸载,则会生成此停止。 要调试此停止:运行 !htrace parameter1 以获取有关句柄的更多信息。
应用程序验证程序显示的信息- 参数 1 - 泄露句柄的值。 如果已启用句柄跟踪,运行 !htrace <handle> 可获取句柄的其他信息。
- 参数 2 - 到分配堆栈跟踪的地址。 运行 dps <地址>以查看分配堆栈。
- 参数 3 - 所有者地址 dll 名称。 运行 du <地址>以读取 dll 名称。
- 参数 4 - 所有者 dll 的基础。 运行 .reload <dll_name> = <地址>以重新加载所有者 dll。 使用“lm”获取更多已加载和未加载模块的相关信息。
- 测试层: 泄露
- 停止 ID: HANDLE
- 停止代码: 900NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
HKEY 已泄露。
可能的原因如果注册表键值的所有者 dll 在拥有资源时被动态卸载,则会生成此停止。
应用程序验证程序显示的信息- 参数 1 - 泄露 HKEY 的值。
- 参数 2 - 到分配堆栈跟踪的地址。 运行 dps <地址>以查看分配堆栈。
- 参数 3 - 所有者地址 dll 名称。 运行 du <地址>以读取 dll 名称。
- 参数 4 - 所有者 dll 的基础。 运行 .reload <dll_name> = <地址>以重新加载所有者 dll。 使用“lm”获取更多已加载和未加载模块的相关信息。
- 测试层: 泄露
- 停止 ID: REGISTRY
- 停止代码: 900NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
虚拟预留已泄露。
可能的原因如果虚拟预留的所有者 dll 在拥有资源时被动态卸载,则会生成此停止。
应用程序验证程序显示的信息- 参数 1 - 泄露的预订地址。
- 参数 2 - 到分配堆栈跟踪的地址。 运行 dps <地址>以查看分配堆栈。
- 参数 3 - 所有者地址 dll 名称。 运行 du <地址>以读取 dll 名称。
- 参数 4 - 所有者 dll 的基础。 运行 .reload <dll_name> = <地址>以重新加载所有者 dll。 使用“lm”获取更多已加载和未加载模块的相关信息。
- 测试层: 泄露
- 停止 ID: VIRTUAL_RESERVATION
- 停止代码: 900NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
一个 BSTR 已泄露。
可能的原因如果 SysString 的所有者 dll 在拥有资源时被动态卸载,则会生成此停止。
应用程序验证程序显示的信息- 参数 1 - 泄露 BSTR 的地址。 运行 !heap -p -a <地址>以获取有关分配的其他信息。
- 参数 2 - 到分配堆栈跟踪的地址。 运行 dps <地址>以查看分配堆栈。
- 参数 3 - 所有者地址 dll 名称。 运行 du <地址>以读取 dll 名称。
- 参数 4 - 所有者 dll 的基础。 运行 .reload <dll_name> = <地址>以重新加载所有者 dll。 使用“lm”获取更多已加载和未加载模块的相关信息。
- 测试层: 泄露
- 停止 ID: SYSSTRING
- 停止代码: 900NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
电源通知尚未取消注册。
可能的原因如果 dll 注册了电源通知,但在未取消注册的情况下被动态卸载,则会生成此停止。
应用程序验证程序显示的信息- 参数 1 - 电源通知注册的地址。
- 参数 2 - 到注册堆栈跟踪的地址。 运行 dps <地址>以查看分配堆栈。
- 参数 3 - 所有者地址 dll 名称。 运行 du <地址>以读取 dll 名称。
- 参数 4 - 所有者 dll 的基础。 运行 .reload <dll_name> = <地址>以重新加载所有者 dll。 使用“lm”获取更多已加载和未加载模块的相关信息。
- 测试层: 泄露
- 停止 ID: POWER_NOTIFICATION
- 停止代码: 900NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
锁停止详细信息
线程不能拥有关键部分。
可能的原因如果线程(线程 ID 为参数 1)被终止、暂停或处于无法保持临界区的状态(工作线程完成了一个工作项),则会生成此停止。 当前线程就是原因。 要调试此停止,请使用以下调试器命令:$ kb - 获取当前堆栈跟踪。 如果当前线程是关键部分的所有者,则它可能正在调用 ExitThread。 当前线程应在退出前释放关键部分。 如果当前线程正在调用 TerminateThread 或 SuspendThread,则不应该对持有关键部分的线程执行此操作。 $ !cs -s parameter2 - 转储有关此关键部分的信息。 $ ln parameter2 - 显示关键部分地址附近的符号。 这应该有助于识别泄露的关键部分。 $ dps parameter4 - 转储此关键部分初始化的堆栈跟踪。
应用程序验证程序显示的信息- 参数 1 - 线程 ID。
- 参数 2 - 关键部分地址。
- 参数 3 - 关键部分调试信息地址。
- 参数 4 - 关键部分初始化堆栈跟踪。
- 测试层: 锁
- 停止 ID: EXIT_THREAD_OWNS_LOCK
- 停止代码: 200NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
卸载包含活动关键部分的 DLL。
可能的原因如果 DLL 的全局变量包含关键部分,并且 DLL 已卸载但关键部分尚未删除,则会生成此停止。 要调试此停止,请使用以下调试器命令:$ du parameter3 - 转储原因 DLL 的名称。 $ .reload dllname 或 .reload dllname = parameter4 - 重新加载该 DLL 的符号。 $ !cs -s parameter1 - 转储有关此关键部分的信息。 $ ln parameter1 - 显示关键部分地址附近的符号。 这应该有助于识别泄露的关键部分。 $ dps parameter2 - 转储此关键部分初始化的堆栈跟踪。
应用程序验证程序显示的信息- 参数 1 - 关键部分地址。
- 参数 2 - 关键部分初始化堆栈跟踪。
- 参数 3 - DLL 名称地址。
- 参数 4 - DLL 基址。
- 测试层: 锁
- 停止 ID: LOCK_IN_UNLOADED_DLL
- 停止代码: 200NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
释放包含活动关键部分的堆块。
可能的原因如果堆分配包含关键部分、分配被释放且关键部分尚未被删除,则会生成此停止。 要调试此停止,请使用以下调试器命令:$ !cs -s parameter1 - 转储有关此关键部分的信息。 $ ln parameter1 - 显示关键部分地址附近的符号。 这应该有助于识别泄露的关键部分。 $ dps parameter2 - 转储此关键部分初始化的堆栈跟踪。 $ parameter3 和 parameter4 可能有助于了解此堆块是在哪里分配的(分配的大小可能很重要)。
应用程序验证程序显示的信息- 参数 1 - 关键部分地址。
- 参数 2 - 关键部分初始化堆栈跟踪。
- 参数 3 - 堆块地址。
- 参数 4 - 堆块大小。
- 测试层: 锁
- 停止 ID: LOCK_IN_FREED_HEAP
- 停止代码: 200NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
双重初始化或关键部分损坏。
可能的原因通常情况下,如果关键部分被初始化超过一次,则会生成此停止。 在本例中,parameter3 和 parameter4 是其中两个初始化的堆栈跟踪地址。 有时,如果关键部分或其调试信息结构已损坏,则也有可能出现这种停止。 在第二种情况下,parameter3 和 parameter4 可能无效且无用。 要调试此停止:$ !cs -s -d parameter2 - 转储有关这一关键部分的信息。 $ ln parameter1 - 显示关键部分地址附近的符号。 如果这是一个全局变量,则这可能有助于确定关键部分。 $ dps parameter3 和 dps parameter4 - 确定初始化此关键部分的两个代码路径。
应用程序验证程序显示的信息- 参数 1 - 关键部分地址。
- 参数 2 - 活动列表中调试信息结构的地址。
- 参数 3 - 首次初始化堆栈跟踪。
- 参数 4 - 第二次初始化堆栈跟踪。
- 测试层: 锁
- 停止 ID: LOCK_DOUBLE_INITIALIZE
- 停止代码: 200NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
释放包含活动关键部分的内存。
可能的原因如果包含关键部分的内存已释放,但关键部分尚未使用 DeleteCriticalSection 删除,则会生成此停止。 要调试此停止,请使用以下调试器命令:$ !cs -s -d parameter2 - 转储有关此关键部分的信息。 $ dps parameter3 - 标识初始化该关键部分的代码路径。 在大多数情况下,锁验证程序会立即检测到堆分配、DLL 范围、虚拟内存分配或 MapViewOfFile 映射内存范围中包含的泄漏关键部分,并在这些情况下发出不同的停止指令。 因此,此验证程序停止的情况很少发生。 锁必须位于被内核模式代码释放或被 VirtualFreeEx 等 API 跨进程释放的内存范围内。 最典型的情况是,如果在调试器控制台单击“g”继续执行之前的停止(例如 LOCK_IN_FREED_HEAP 或 LOCK_IN_UNLOADED_DLL),就会遇到这种停止。
应用程序验证程序显示的信息- 参数 1 - 关键部分地址。
- 参数 2 - 关键部分调试信息地址。
- 参数 3 - 关键部分初始化堆栈跟踪。
- 参数 4 - 未使用。
- 测试层: 锁
- 停止 ID: LOCK_IN_FREED_MEMORY
- 停止代码: 200NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
损坏的关键部分。
可能的原因如果关键部分的 DebugInfo 字段指向已释放的内存,则会生成此停止。 通常会在活动关键部分列表中找到另一个有效的 DebugInfo 结构。 在没有损坏的情况下,两个指针应完全相同。 要调试此停止,请使用以下调试器命令:$ !cs -s -d parameter3 - 根据活动列表中调试信息结构的当前内容转储有关此关键部分的信息(此结构很少损坏,因此通常此信息是可信的)。 $ !cs -s parameter1 - 根据关键部分结构的当前内容转储有关该关键部分的信息(该结构已损坏,因此有时该信息不可信)。 $ dps parameter4 - 标识用于初始化该关键部分的代码路径。 在 address parameter1 处转储关键部分并查找损坏模式。 对于 ntdll.dl 的正常符号,可以使用以下命令:$ dt ntdll!_RTL_CRITICAL_SECTION LOCK_ADDRESS $ dt ntdll!_RTL_CRITICAL_SECTION_DEBUG DEBUG_ADDRESS
应用程序验证程序显示的信息- 参数 1 - 关键部分地址。
- 参数 2 - 此关键部分的调试信息地址无效。
- 参数 3 - 活动列表中调试信息的地址。
- 参数 4 - 初始化堆栈跟踪。
- 测试层: 锁
- 停止 ID: LOCK_CORRUPTED
- 停止代码: 200NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
无效的关键部分所有者线程。
可能的原因如果所有者线程 ID 在当前上下文中无效,则会生成此停止。 要调试此停止:$ !cs -s parameter1 - 转储有关这一关键部分的信息。 $ ln parameter1 - 显示关键部分地址附近的符号。 这应该有助于识别关键部分。
应用程序验证程序显示的信息- 参数 1 - 关键部分地址。
- 参数 2 - 拥有的线程。
- 参数 3 - 预计拥有的线程。
- 参数 4 - 关键部分调试信息地址。
- 测试层: 锁
- 停止 ID: LOCK_INVALID_OWNER
- 停止代码: 200NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
关键部分递归计数无效。
可能的原因如果关键部分结构的递归计数字段在当前上下文中无效,则会生成此停止。 要调试此停止:$ !cs -s parameter1 - 转储有关这一关键部分的信息。 $ ln parameter1 - 显示关键部分地址附近的符号。 这应该有助于识别关键部分。
应用程序验证程序显示的信息- 参数 1 - 关键部分地址。
- 参数 2 - 递归计数。
- 参数 3 - 预计的递归计数。
- 参数 4 - 关键部分调试信息地址。
- 测试层: 锁
- 停止 ID: LOCK_INVALID_RECURSION_COUNT
- 停止代码: 200NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
删除锁计数无效的关键部分。
可能的原因如果关键部分被删除或未初始化,则线程将拥有该关键部分,而此时会生成停止。 要调试此停止:$ !cs -s parameter1 - 转储有关这一关键部分的信息。 如果拥有线程为 0,则关键部分尚未初始化。 $ ln parameter1 - 显示关键部分地址附近的符号。 这应该有助于识别关键部分。
应用程序验证程序显示的信息- 参数 1 - 关键部分地址。
- 参数 2 - 锁计数。
- 参数 3 - 预计锁次数。
- 参数 4 - 拥有的线程。
- 测试层: 锁
- 停止 ID: LOCK_INVALID_LOCK_COUNT
- 停止代码: 200NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
关键部分过度释放或损坏。
可能的原因如果关键部分被释放的次数多于当前线程获取的次数,则会生成此停止。 要调试此停止:$ !cs -s parameter1 - 转储有关这一关键部分的信息。 $ !cs -s -d parameter4 - 转储有关此关键部分的信息。 $ ln parameter1 - 显示关键部分地址附近的符号。 这应该有助于识别关键部分。
应用程序验证程序显示的信息- 参数 1 - 关键部分地址。
- 参数 2 - 锁计数。
- 参数 3 - 预计锁次数。
- 参数 4 - 关键部分调试信息地址。
- 测试层: 锁
- 停止 ID: LOCK_OVER_RELEASED
- 停止代码: 200NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
关键部分未初始化。
可能的原因如果关键部分在未初始化的情况下被使用,或在被删除后被使用,则会生成此停止。 要调试此停止:$ ln parameter1 - 显示关键部分地址附近的符号。 这应该有助于识别关键部分。
应用程序验证程序显示的信息- 参数 1 - 关键部分地址。
- 参数 2 - 关键部分调试信息地址。
- 参数 3 - 未使用。
- 参数 4 - 未使用。
- 测试层: 锁
- 停止 ID: LOCK_NOT_INITIALIZED
- 停止代码: 200NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
关键部分已初始化。
可能的原因如果当前线程重新初始化了关键部分,则会生成此停止。 要调试此停止:$ !cs -s parameter1 或 !cs -s -d parameter2 - 转储有关此关键部分的信息。 $ ln parameter1 - 显示关键部分地址附近的符号。 如果这是一个全局变量,则这可能有助于确定关键部分。 $ dps parameter3 - 确定该关键部分首次初始化的代码路径。 $ kb - 显示当前堆栈跟踪,即重新初始化此关键部分。
应用程序验证程序显示的信息- 参数 1 - 关键部分地址。
- 参数 2 - 关键部分调试信息地址。
- 参数 3 - 首次初始化堆栈跟踪。 如果非 NULL,则使用 dps 将其转储
- 参数 4 - 未使用。
- 测试层: 锁
- 停止 ID: LOCK_ALREADY_INITIALIZED
- 停止代码: 200NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
释放包含活动关键部分的虚拟内存。
可能的原因如果当前线程正在对包含活动关键部分的内存块调用 VirtualFree,则会生成此停止。 应用程序在释放该内存之前,应调用该关键部分的 DeleteCriticalSection。 $ kb - 显示当前堆栈跟踪,即调用 VirtualFree。 原因可能是调用了 VirtualFree 的 DLL。 $ !cs -s parameter1 - 转储有关此关键部分的信息。 $ dps parameter2 - 确定该关键部分初始化的代码路径。
应用程序验证程序显示的信息- 参数 1 - 关键部分地址。
- 参数 2 - 关键部分初始化堆栈跟踪。
- 参数 3 - 内存块地址。
- 参数 4 - 内存块大小。
- 测试层: 锁
- 停止 ID: LOCK_IN_FREED_VMEM
- 停止代码: 200NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
解除包含活动关键部分的内存区域映射。
可能的原因如果当前线程正在对包含活动关键部分的内存块调用 UnmapViewOfFile,则会生成此停止。 应用程序在取消映射该内存之前,应调用该关键部分的 DeleteCriticalSection。 $ kb - 显示当前堆栈跟踪,即调用 UnmapViewOfFile。 原因可能是调用 UnmapViewOfFile 的 DLL。 $ !cs -s parameter1 - 转储有关此关键部分的信息。 $ dps parameter2 - 确定该关键部分初始化的代码路径。
应用程序验证程序显示的信息- 参数 1 - 关键部分地址。
- 参数 2 - 关键部分初始化堆栈跟踪。
- 参数 3 - 内存块地址。
- 参数 4 - 内存块大小。
- 测试层: 锁
- 停止 ID: LOCK_IN_UNMAPPED_MEM
- 停止代码: 200NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
当前线程不拥有任何关键部分。
可能的原因如果当前线程正在调用 LeaveCriticalSection,但根据内部验证程序的记录,它并不拥有任何关键部分,则会生成此停止。 如果 parameter2 为零,则可能是当前线程中的一个错误。 要么是它尝试离开没有进入的关键部分,要么是它对同一关键部分调用 LeaveCriticalSection 的次数多于调用 EnterCriticalSection 的次数。 如果 parameter2 不为零(为负整数),则内部校验数据结构可能已损坏。
应用程序验证程序显示的信息- 参数 1 - 关键部分地址。
- 参数 2 - 当前线程拥有的关键部分数。
- 参数 3 - 未使用
- 参数 4 - 未使用
- 测试层: 锁
- 停止 ID: THREAD_NOT_LOCK_OWNER
- 停止代码: 200NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
使用专用于另一个 DLL 的关键部分。
可能的原因如果当前线程尝试使用另一个 DLL 中的专用锁,则会生成此停止。 例如,a.dll 尝试进入 ntdll.dll 内定义的关键部分。 专用锁不能跨 DLL 使用。
应用程序验证程序显示的信息- 参数 1 - 关键部分地址。
- 参数 2 - 未使用。
- 参数 3 - 未使用
- 参数 4 - 未使用
- 测试层: 锁
- 停止 ID: LOCK_PRIVATE
- 停止代码: 200NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
SRWLock 停止详细信息
SRW 锁未初始化。
可能的原因如果线程尝试使用未初始化的 SRW 锁 (Param1),则会生成此停止。 $ kb - 获取当前堆栈跟踪。 这就是使用 SRW 锁的位置。 在使用 SRW 锁之前,应使用 InitializeSRWLock 对其进行初始化。
应用程序验证程序显示的信息- 参数 1 - SRW 锁
- 参数 2 - 未使用
- 参数 3 - 未使用
- 参数 4 - 未使用
- 测试层: SRWLock
- 停止 ID: NOT_INITIALIZED
- 停止代码: 250NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
SRW 锁已经初始化。
可能的原因如果 SRW 锁 (Param1) 正在重新初始化,则会生成此停止。 如果 SRW 锁正在被其他线程主动使用,则重新初始化锁将导致应用程序出现不可预知的行为,包括挂起和崩溃。 如果 SRW 锁是静态初始化的,则初始化堆栈跟踪可能会显示获取。 $ kb - 获取当前堆栈跟踪。 这是 SRW 锁重新初始化的位置。 $ dps Param3 - 获取 SRW 锁初始化堆栈跟踪。 如果锁是静态初始化的,则堆栈跟踪可能会显示获取。
应用程序验证程序显示的信息- 参数 1 - SRW 锁
- 参数 2 - 初始化 SRW 锁的线程的线程 ID。
- 参数 3 - 初始化堆栈跟踪地址。 使用 dps <地址>查看 SRW 锁的初始化位置。
- 参数 4 - 未使用
- 测试层: SRWLock
- 停止 ID: ALREADY_INITIALIZED
- 停止代码: 250NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
SRW 锁上的“获取释放“不匹配。
可能的原因如果使用错误的释放 API 来释放 SRW 锁 (Param1),则会生成此停止。 如果 SRW 锁是为共享访问而获取的,并且正在使用独占释放 API 进行释放,或者 SRW 锁是为独占访问而获取的,并且正在使用共享释放 API 进行释放。 这可能导致应用程序出现不可预测的行为,包括挂起和崩溃。 $ kb - 获取当前堆栈跟踪。 这就是使用错误的 API 释放 SRW 锁的位置。 $ dps Param3 - 获取 SRW 锁获取堆栈跟踪。
应用程序验证程序显示的信息- 参数 1 - SRW 锁
- 参数 2 - 获取 SRW 锁的线程的线程 ID。
- 参数 3 - 获取堆栈跟踪的地址。 使用 dps <地址>查看获取 SRW 锁的位置。
- 参数 4 - 未使用
- 测试层: SRWLock
- 停止 ID: MISMATCHED_ACQUIRE_RELEASE
- 停止代码: 250NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
SRW 锁被同一线程递归获取。
可能的原因如果 SRW 锁 (Param1) 被同一线程递归获取,则会生成此停止。 这将导致死锁,线程将被无限期阻止。 在独占模式下递归获取 SRW 锁会导致死锁。 当有线程在等待独占访问时,在共享模式下递归获取 SRW 锁会导致死锁。 请考虑以下示例:- 线程 A 以共享模式获取 SRW 锁 - 线程 B 尝试以独占模式获取 SRW 锁并等待 - 线程 A 尝试以共享模式递归获取 SRW 锁。 只要没有专属等待程序(在本例中为 B),此操作就会成功。 由于 SRW 锁不存在写入器不足问题,因此线程 A 会在线程 B 后面等待。现在,线程 B 正在等待线程 A,而线程 A 又在等待线程 B,这就造成了循环等待,从而导致死锁。 $ kb - 获取当前堆栈跟踪。 这就是 SRW 锁被递归获取的位置。 $ dps Param2 - 获取第一次获取的堆栈跟踪。
应用程序验证程序显示的信息- 参数 1 - SRW 锁
- 参数 2 - 第一次获取的堆栈跟踪地址。 使用 dps <地址>查看获取 SRW 锁的位置。
- 参数 3 - 未使用
- 参数 4 - 未使用
- 测试层: SRWLock
- 停止 ID: RECURSIVE_ACQUIRE
- 停止代码: 250NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
正在退出或终止的线程拥有一个 SRW 锁。
可能的原因如果拥有 SRW 锁 (Param1) 的线程 (Param2) 正在退出或终止,则会生成此停止。 这将导致 SRW 锁成被孤立,尝试获取该锁的线程将被无限期阻止。 $ kb - 获取当前堆栈跟踪。 这是线程退出或终止的位置。 $ dps Param3 - 获取 SRW 锁获取堆栈跟踪。
应用程序验证程序显示的信息- 参数 1 - SRW 锁
- 参数 2 - 正在退出或终止的线程的线程 ID。
- 参数 3 - 获取堆栈跟踪的地址。 使用 dps <地址>查看获取 SRW 锁的位置。
- 参数 4 - 未使用
- 测试层: SRWLock
- 停止 ID: EXIT_THREAD_OWNS_LOCK
- 停止代码: 250NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
被释放的 SRW 锁并非由此线程获取。
可能的原因如果 SRW 锁 (Param1) 被未获取该锁的线程 (Param2) 释放,则会生成此停止。 这是很难做到的不正常编程做法,会导致应用程序出现不可预测的行为。 $ kb - 获取当前堆栈跟踪。 这是线程释放其未获取的 SRW 锁的位置。 $ dps Param4 - 获取 SRW 锁获取堆栈跟踪。
应用程序验证程序显示的信息- 参数 1 - SRW 锁
- 参数 2 - 当前 ThreadId。
- 参数 3 - 获取 SRW 锁的线程的线程 ID。
- 参数 4 - 获取堆栈跟踪的地址。 使用 dps <地址>查看获取 SRW 锁的位置。
- 测试层: SRWLock
- 停止 ID: INVALID_OWNER
- 停止代码: 250NAN
- 严重性: 警告
- 一次性错误:
- 错误报告: 无
- 记录到文件: 是
- 创建回溯: 是
被释放的内存包含一个活动的 SRW 锁。
可能的原因如果被释放的内存地址 (Param1) 包含仍在使用的活动 SRW 锁,则会生成此停止。 这会导致应用程序出现不可预测的行为,包括崩溃和挂起。 $ kb - 获取当前堆栈跟踪。 这是释放包含活动 SRW 锁的内存的位置。 $ dps Param4 - 获取 SRW 锁获取堆栈跟踪。
应用程序验证程序显示的信息- 参数 1 - SRW 锁
- 参数 2 - 被释放内存的地址。
- 参数 3 - 获取 SRW 锁的线程的线程 ID。
- 参数 4 - 获取堆栈跟踪的地址。 使用 dps <地址>查看获取 SRW 锁的位置。
- 测试层: SRWLock
- 停止 ID: IN_FREED_MEMORY
- 停止代码: 250NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
正在卸载的 DLL 包含活动的 SRW 锁。
可能的原因如果正在卸载的 DLL (Param2) 包含一个仍在使用的活动 SRW 锁 (Param1),则会生成此停止。 这会导致应用程序出现不可预测的行为,包括崩溃和挂起。 $ kb - 获取当前堆栈跟踪。 这是正在卸载包含活动 SRW 锁的 DLL 的位置。 $ du Param2 - 查找正在卸载的 DLL 的名称。 $ dps Param4 - 获取 SRW 锁获取堆栈跟踪。
应用程序验证程序显示的信息- 参数 1 - SRW 锁
- 参数 2 - 正在卸载的 DLL 的名称地址。 使用 du <地址>查看名称。
- 参数 3 - 获取 SRW 锁的线程的线程 ID。
- 参数 4 - 获取堆栈跟踪的地址。 使用 dps <地址>查看获取 SRW 锁的位置。
- 测试层: SRWLock
- 停止 ID: IN_UNLOADED_DLL
- 停止代码: 250NAN
- 严重性: 警告
- 一次性错误:
- 错误报告: 无
- 记录到文件: 是
- 创建回溯: 是
内存停止详细信息
释放大小或起始地址无效的虚拟内存块。
可能的原因如果应用程序验证程序检测到 VirtualFree 或 DLL 卸载的起始地址或内存分配的大小无效,则会生成此停止。 在 DLL 卸载的情况下,这可能意味着已加载 DLL 列表内部的内存损坏。 要调试此停止,需要查看当前堆栈跟踪以及即将释放的内存地址和大小,并尝试确定它们无效的原因。
应用程序验证程序显示的信息- 参数 1 - 分配基址。
- 参数 2 - 内存区域大小。
- 参数 3 - 未使用。
- 参数 4 - 未使用。
- 测试层: 内存
- 停止 ID: INVALID_FREEMEM
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
虚拟分配调用不正确。
可能的原因如果应用验证程序检测到 VirtualAlloc 调用的起始地址或内存分配的大小无效,则会生成此停止。 要调试此停止,请查看当前堆栈跟踪 (kb) 以及即将分配的内存地址和大小,并尝试确定它们无效的原因。
应用程序验证程序显示的信息- 参数 1 - 指向分配基址的指针。
- 参数 2 - 指向内存区域大小的指针。
- 参数 3 - 未使用
- 参数 4 - 未使用
- 测试层: 内存
- 停止 ID: INVALID_ALLOCMEM
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
映射视图调用不正确。
可能的原因如果应用验证程序检测到 MapViewOfFile 调用的基址或映射大小无效,则会生成此停止。 要调试此停止,请查看当前堆栈跟踪 (kb) 以及即将映射的内存地址和大小,并尝试确定它们无效的原因。
应用程序验证程序显示的信息- 参数 1 - 指向映射基址的指针。
- 参数 2 - 指向视图大小的指针。
- 参数 3 - 未使用。
- 参数 4 - 未使用。
- 测试层: 内存
- 停止 ID: INVALID_MAPVIEW
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
探测无效地址。
可能的原因如果应用验证程序检测到 IsBadXXXPtr 调用的待探测内存缓冲区地址无效(如内核模式地址,而非正常用户模式地址),则会生成此停止。 要调试此停止,请查看当前堆栈跟踪 (kb),并尝试确定 IsBadXXXPtr 函数的调用方最终使用无效地址的原因。 很多时候,地址是纯虚假的,例如一个未初始化的指针。 MSDN 库列出了应用程序不应使用 IsBadXXXPtr API 的几个原因:在抢占式多任务环境中,其他线程有可能改变进程对被测内存的访问。 取消引用可能无效的指针会禁用其他线程中的堆栈扩展。 当堆栈扩展被禁用时,线程耗尽堆栈会导致父进程立即终止,而不会弹出错误窗口或诊断信息。 进程中的线程应相互配合,使其中一个线程不会释放另一个线程需要的内存。 使用此函数并不意味着不需要这样做。 如果不这样做,应用程序可能会以不可预知的方式失败。 鉴于上述原因,我们建议永远不要使用这些 API。
应用程序验证程序显示的信息- 参数 1 - 起始地址。
- 参数 2 - 内存块大小。
- 参数 3 - 无效地址。
- 参数 4 - 未使用。
- 测试层: 内存
- 停止 ID: PROBE_INVALID_ADDRESS
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
探测空闲内存。
可能的原因如果应用验证程序检测到针对空闲内存分配的 IsBadXXXPtr 调用,则会生成此停止。 这是非常糟糕的,因为在其他一些情况下,这些内存可能已经被其他分配重复使用了。 由于当前代码路径 (kb) 并不拥有该内存,因此它最终可能会破坏别人的内存,从而造成灾难性的后果。 要停止调试,请查看当前堆栈跟踪 (kb),并尝试确定 IsBadXXXPtr 函数的调用方为什么最终会探测到空闲内存。 地址可以是纯虚假的(例如未初始化的指针),也可能是已经释放的内存。 如果内存已被 VirtualFree 或 UnmapViewOfFile API 之一释放,则“!avrf -vs -a parameter3”将搜索分配/释放该地址的代码路径的堆栈跟踪日志,并在堆栈跟踪可用时显示这些堆栈跟踪。 这可能会显示释放该内存的堆栈跟踪。 更常见的情况是,内存是已经释放的堆分配。 为检查这种可能性,“!avrf -hp -a parameter3”将搜索从堆中分配/释放该地址的代码路径的堆栈跟踪日志,如有,则会显示这些堆栈跟踪。 MSDN 库列出了应用程序不应使用 IsBadXXXPtr API 的几个原因:在抢占式多任务环境中,其他线程有可能改变进程对被测内存的访问。 取消引用可能无效的指针会禁用其他线程中的堆栈扩展。 当堆栈扩展被禁用时,线程耗尽堆栈会导致父进程立即终止,而不会弹出错误窗口或诊断信息。 进程中的线程应相互配合,使其中一个线程不会释放另一个线程需要的内存。 使用此函数并不意味着不需要这样做。 如果不这样做,应用程序可能会以不可预知的方式失败。 鉴于上述原因,我们建议永远不要使用这些 API。
应用程序验证程序显示的信息- 参数 1 - 起始地址。
- 参数 2 - 内存块大小。
- 参数 3 - 空闲内存页地址。
- 参数 4 - 未使用。
- 测试层: 内存
- 停止 ID: PROBE_FREE_MEM
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
探测防护页。
可能的原因如果应用验证程序检测到至少包含一个 GUARD_PAGE 的内存分配调用 IsBadXXXPtr,则会生成此停止。 这是非常糟糕的,因为 GUARD_PAGE 很有可能是线程当前堆栈的终点。 正如 MSDN 库中所记录的那样:取消引用可能无效的指针会导致其他线程无法扩展堆栈。 当堆栈扩展被禁用时,线程耗尽堆栈会导致父进程立即终止,而不会弹出错误窗口或诊断信息。 要停止调试,请查看当前堆栈跟踪 (kb),并尝试确定 IsBadXXXPtr 函数的调用方为何最终探测到了 GUARD_PAGE。 MSDN 库列出了应用程序不应使用 IsBadXXXPtr API 的几个原因:在抢占式多任务环境中,其他线程有可能改变进程对被测内存的访问。 取消引用可能无效的指针会禁用其他线程中的堆栈扩展。 当堆栈扩展被禁用时,线程耗尽堆栈会导致父进程立即终止,而不会弹出错误窗口或诊断信息。 进程中的线程应相互配合,使其中一个线程不会释放另一个线程需要的内存。 使用此函数并不意味着不需要这样做。 如果不这样做,应用程序可能会以不可预知的方式失败。 鉴于上述原因,我们建议永远不要使用这些 API。
应用程序验证程序显示的信息- 参数 1 - 起始地址。
- 参数 2 - 内存块大小。
- 参数 3 - 保护页面地址。
- 参数 4 - 未使用。
- 测试层: 内存
- 停止 ID: PROBE_GUARD_PAGE
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
探测 NULL 地址。
可能的原因如果应用验证程序检测到带有 NULL 地址的 IsBadXXXPtr 调用,则会生成此停止。 要调试此停止,请查看当前堆栈跟踪 (kb),并尝试确定 IsBadXXXPtr 函数的调用方最终使用 NULL 地址的原因。 这通常是由于有人没有检查某个内存分配函数的返回值所致。 例如,下面的代码不正确:int main (void) { PVOID p; p = malloc (1024); Use (p); return 0; } void Use (PVOID p) { if (IsBadReadPtr (p)) { return; } // // p is safe to be used here. // }。这段代码应该改写为:int main (void) { PVOID p; p = malloc (1024); if (NULL == p)) { return -1; } Use (p); return 0; } void Use (PVOID p) { // // p is safe to be used here. // } MSDN 库列出了应用程序不应使用 IsBadXXXPtr API 的几个原因:在抢占式多任务环境中,其他线程有可能改变进程对被测内存的访问。 取消引用可能无效的指针会禁用其他线程中的堆栈扩展。 当堆栈扩展被禁用时,线程耗尽堆栈会导致父进程立即终止,而不会弹出错误窗口或诊断信息。 进程中的线程应相互配合,使其中一个线程不会释放另一个线程需要的内存。 使用此函数并不意味着不需要这样做。 如果不这样做,应用程序可能会以不可预知的方式失败。 鉴于上述原因,我们建议永远不要使用这些 API。
应用程序验证程序显示的信息- 参数 1 - 未使用。
- 参数 2 - 未使用。
- 参数 3 - 未使用。
- 参数 4 - 未使用。
- 测试层: 内存
- 停止 ID: PROBE_NULL
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
探测内存块的起始地址或大小无效。
可能的原因如果应用验证程序检测到 IsBadXXXPtr 调用的起始地址无效(如内核模式地址,而非正常的用户模式地址),或者要探测的内存缓冲区大小无效,则会生成此停止。 要调试此停止,请查看当前堆栈跟踪 (kb),并尝试确定 IsBadXXXPtr 函数的调用方最终使用无效地址或大小的原因。 很多时候,地址或大小都是纯虚假的,例如未初始化的变量。 MSDN 库列出了应用程序不应使用 IsBadXXXPtr API 的几个原因:在抢占式多任务环境中,其他线程有可能改变进程对被测内存的访问。 取消引用可能无效的指针会禁用其他线程中的堆栈扩展。 当堆栈扩展被禁用时,线程耗尽堆栈会导致父进程立即终止,而不会弹出错误窗口或诊断信息。 进程中的线程应相互配合,使其中一个线程不会释放另一个线程需要的内存。 使用此函数并不意味着不需要这样做。 如果不这样做,应用程序可能会以不可预知的方式失败。 鉴于上述原因,我们建议永远不要使用这些 API。
应用程序验证程序显示的信息- 参数 1 - 起始地址。
- 参数 2 - 内存块大小。
- 参数 3 - 未使用。
- 参数 4 - 未使用。
- 测试层: 内存
- 停止 ID: PROBE_INVALID_START_OR_SIZE
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
卸载具有无效大小或起始地址的 DLL。
可能的原因如果应用验证程序检测到 DLL 卸载的起始地址或 DLL 内存范围的大小无效,则会生成此停止。 这可能意味着内部 ntdll.dll 加载的 DLL 列表出现了内存损坏。
应用程序验证程序显示的信息- 参数 1 - DLL 内存基址。
- 参数 2 - DLL 内存范围大小。
- 参数 3 - DLL 名称地址。 使用 du 将其转储。
- 参数 4 - 未使用。
- 测试层: 内存
- 停止 ID: INVALID_DLL_RANGE
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
释放当前线程堆栈地址范围内的内存块。
可能的原因如果应用验证程序检测到某个内存块的 VirtualFree 实际上是当前线程栈 (!) 的一部分,则会生成此停止。 要停止调试,请查看当前堆栈跟踪 (kb),并尝试了解为什么调用 VirtualFree 的函数认为内存块是动态分配或映射的,而实际上是从堆栈分配的内存。
应用程序验证程序显示的信息- 参数 1 - 分配基址。
- 参数 2 - 内存区域大小。
- 参数 3 - 堆栈下限地址。
- 参数 4 - 堆栈上限地址。
- 测试层: 内存
- 停止 ID: FREE_THREAD_STACK_MEMORY
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
VirtualFree 操作的 FreeType 参数不正确。
可能的原因如果应用验证程序检测到 VirtualFree 的 FreeType 参数值不正确,则会生成此停止。 此参数只有两个可接受的值,即 MEM_DECOMMIT 和 MEM_RELEASE。 如果调用 VirtualFree 时使用了除这两个值之外的任何其他值,则 VirtualFree 将无法释放内存。 要停止调试,请查看当前堆栈跟踪 (kb):VirtualFree 的调用方可能是原因。
应用程序验证程序显示的信息- 参数 1 - 应用程序使用的值不正确。
- 参数 2 - 预期正确的值 1。
- 参数 3 - 预期正确的值 2。
- 参数 4 - 未使用。
- 测试层: 内存
- 停止 ID: INVALID_FREE_TYPE
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
尝试释放本已释放的虚拟内存块。
可能的原因如果应用验证程序检测到一个地址的 VirtualFree 已经释放,则会生成此停止。 要调试此停止,请查看当前堆栈跟踪 (kb),并尝试确定为什么内存已经释放,但应用程序却会尝试再次释放它。 “avrf -vs -a parameter1”将搜索分配/释放该地址的代码路径的堆栈跟踪日志,并在堆栈跟踪可用时显示这些日志。 这可能会显示释放该内存的堆栈跟踪。
应用程序验证程序显示的信息- 参数 1 - 内存块地址。
- 参数 2 - 未使用。
- 参数 3 - 未使用。
- 参数 4 - 未使用。
- 测试层: 内存
- 停止 ID: MEM_ALREADY_FREE
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
VirtualFree (MEM_RELEASE) 操作的大小参数不正确。
可能的原因如果应用验证程序检测到 VirtualFree (MEM_RELEASE),且参数 dwSize 的值非零,则会生成此停止。 使用 MEM_RELEASE 时,此参数唯一可接受的值是 0。 如果在调用 VirtualFree 时使用 0 以外的任何其他值,则 VirtualFree 将无法释放内存。 要停止调试,请查看当前堆栈跟踪 (kb):VirtualFree 的调用方可能是原因。
应用程序验证程序显示的信息- 参数 1 - 应用程序使用的大小不正确。
- 参数 2 - 预计正确的大小 (0)。
- 参数 3 - 未使用。
- 参数 4 - 未使用。
- 测试层: 内存
- 停止 ID: INVALID_FREE_SIZE
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
DLL 入口点例程中出现意外异常。
可能的原因如果 DLL 的入口点 (DllMain) 函数出现异常,则会生成此停止。 错误的一个原因示例是:如果 DllMain(DLL_PROCESS_ATTACH) 出现异常,Windows DLL 加载程序将:- 捕获并隐藏异常;- 卸载 DLL 而不调用 DllMain(DLL_PROCESS_DETACH)。 因此,在许多情况下,DLL 已经分配了一些资源,然后就会引发异常,而且它没有机会在 DllMain (DLL_PROCESS_DETACH) 上释放这些资源。 要调试此停止:$ du parameter1 - 显示 DLL 名称;$ .exr parameter2 - 显示异常信息;$ .cxr parameter3 后跟 kb - 显示异常上下文信息和异常发生时的堆栈跟踪;$ parameter4 是内部校验结构的地址,对大多数校验用户来说没有任何意义。
应用程序验证程序显示的信息- 参数 1 - DLL 名称(使用 du 将其转储)。
- 参数 2 - 异常记录。 使用 .exr 显示它。
- 参数 3 - 上下文记录。 使用 .cxr 显示它。
- 参数 4 - 验证程序 dll 描述符
- 测试层: 内存
- 停止 ID: DLL_UNEXPECTED_EXCEPTION
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
线程函数中出现意外异常。
可能的原因如果线程函数引发异常,则会生成此停止。 这很糟糕,因为整个进程都会被终止。 要调试此停止:$ parameter1 可能对异常类型很重要。 例如,异常代码 C0000005 表示访问冲突;$ .exr parameter2 - 显示异常信息;$ .cxr parameter3 后跟 kb - 显示异常上下文信息;
应用程序验证程序显示的信息- 参数 1 - 异常代码。
- 参数 2 - 异常记录。 使用 .exr 显示它。
- 参数 3 - 上下文记录。 使用 .cxr 显示它。
- 参数 4 - 未使用。
- 测试层: 内存
- 停止 ID: THREAD_UNEXPECTED_EXCEPTION
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
探测内存时出现意外异常。
可能的原因如果在调用 IsBadXXXPtr 时出现异常,则会生成此停止。 这意味着我们正在探测的内存缓冲区实际上没有调用方假设的保护,或者内存已经被释放等。请参阅上文关于其他停止代码(PROBE_INVALID_ADDRESS、PROBE_FREE_MEM、PROBE_GUARD_PAGE、PROBE_NULL、PROBE_INVALID_START_OR_SIZE)的讨论,了解为什么不推荐使用 IsBadXXXPtr API 的更多示例。 要调试此停止:$ parameter1 通常为 C0000005,表示访问冲突;$ .exr parameter2 - 显示异常信息;$ .cxr parameter3 后跟 kb - 显示异常上下文信息和异常发生时的堆栈跟踪;
应用程序验证程序显示的信息- 参数 1 - 异常代码。
- 参数 2 - 异常记录。 使用 .exr 显示它。
- 参数 3 - 上下文记录。 使用 .cxr 显示它。
- 参数 4 - 未使用
- 测试层: 内存
- 停止 ID: PROBE_UNEXPECTED_EXCEPTION
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
尝试重置 NULL 地址。
可能的原因如果应用验证程序检测到 VirtualFree (MEM_RESET) 调用的第一个参数为 NULL,则会生成此停止。 MEM_RESET 只能用于已分配的内存,因此 NULL 不是有效的第一个参数。
应用程序验证程序显示的信息- 参数 1 - 未使用。
- 参数 2 - 未使用。
- 参数 3 - 未使用。
- 参数 4 - 未使用。
- 测试层: 内存
- 停止 ID: INVALID_MEM_RESET
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
释放当前线程堆栈地址范围内的堆内存块。
可能的原因如果应用验证程序检测到某个内存块的 HeapFree,而该内存块实际上是当前线程堆栈 (!) 的一部分,则会生成此停止。 要停止调试,请查看当前堆栈跟踪 (kb),并尝试了解为什么调用 HeapFree 的函数认为内存块是动态分配或映射的,而实际上是从堆栈分配的内存。
应用程序验证程序显示的信息- 参数 1 - 分配基址。
- 参数 2 - 内存区域大小。
- 参数 3 - 堆栈下限地址。
- 参数 4 - 堆栈上限地址。
- 测试层: 内存
- 停止 ID: FREE_THREAD_STACK_MEMORY_AS_HEAP
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
取消映射当前线程堆栈地址范围内内存区域。
可能的原因如果应用验证程序检测到一个内存块的 UnmapViewOfFile,而该内存块实际上是当前线程堆栈 (!) 的一部分,则会生成此停止。 要停止调试,请查看当前堆栈跟踪 (kb),并尝试了解为什么调用 UnmapViewOfFile 的函数认为内存块是动态分配或映射的,而实际上是从堆栈分配的内存。
应用程序验证程序显示的信息- 参数 1 - 分配基址。
- 参数 2 - 内存区域大小。
- 参数 3 - 堆栈下限地址。
- 参数 4 - 堆栈上限地址。
- 测试层: 内存
- 停止 ID: FREE_THREAD_STACK_MEMORY_AS_MAP
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
RTL_RESOURCE 地址不正确。
可能的原因如果应用程序尝试使用 NULL 或其他不正确的地址(如内核模式地址)作为有效对象的地址,则会生成此停止。 RtlInitializeResource (NULL) 是一个不正确的 API 调用,会触发此类验证程序停止。 param1 是使用的错误地址,则原因在堆栈跟踪中(其显示带有 kb)。
应用程序验证程序显示的信息- 参数 1 - 地址。
- 参数 2 - 未使用。
- 参数 3 - 未使用。
- 参数 4 - 未使用。
- 测试层: 内存
- 停止 ID: INVALID_RESOURCE_ADDRESS
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
关键部分地址无效。
可能的原因如果应用程序尝试使用 NULL 或其他不正确的地址(如内核模式地址)作为有效对象的地址,则会生成此停止。 EnterCriticalSection(NULL) 是一个不正确的 API 调用,会触发此类验证程序停止。 param1 是使用的错误地址,则原因在堆栈跟踪中(其显示带有 kb)。
应用程序验证程序显示的信息- 参数 1 - 地址。
- 参数 2 - 未使用。
- 参数 3 - 未使用。
- 参数 4 - 未使用。
- 测试层: 内存
- 停止 ID: INVALID_CRITSECT_ADDRESS
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
尝试在不可执行内存中执行代码。
可能的原因如果应用程序尝试从一个不可执行或空闲的地址运行代码,则会生成此停止。 要调试此停止:$ u parameter2 - 用于反汇编原因代码;$ .exr parameter3 - 用于显示异常信息;$ .cxr parameter4 后跟 kb - 用于显示异常上下文信息和异常发生时的堆栈跟踪。
应用程序验证程序显示的信息- 参数 1 - 正在访问的地址。
- 参数 2 - 执行无效访问的代码。
- 参数 3 - 异常记录。 使用 .exr 显示它。
- 参数 4 - 上下文记录。 使用 .cxr 显示它。
- 测试层: 内存
- 停止 ID: THREAD_UNEXPECTED_EXCEPTION_CODE
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
初始化输出缓冲区时出现意外异常。
可能的原因如果在初始化作为 Win32 或 CRT API 输出参数指定的缓冲区时出现异常,则会生成此停止。 这通常意味着指定的输出缓冲区大小不正确。 要调试此停止:$ .exr parameter3 - 显示异常信息;$ .cxr parameter4 后跟 kb - 显示异常上下文信息和异常发生时的堆栈跟踪。
应用程序验证程序显示的信息- 参数 1 - 缓冲区起始地址。
- 参数 2 - 缓冲区大小。
- 参数 3 - 异常记录。 使用 .exr 显示它。
- 参数 4 - 上下文记录。 使用 .cxr 显示它。
- 测试层: 内存
- 停止 ID: OUTBUFF_UNEXPECTED_EXCEPTION
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
尝试查找堆块大小时出现意外异常。
可能的原因如果在为一个正在释放的堆块调用 HeapSize 时出现异常,则会生成此停止。 这通常意味着指定的堆块地址不正确或堆已损坏。 要调试此停止:$ .exr parameter3 - 显示异常记录;$ .cxr parameter4 后跟 kb - 显示异常上下文信息和异常发生时的堆栈跟踪。
应用程序验证程序显示的信息- 参数 1 - 要释放的堆块地址。
- 参数 2 - 堆句柄。
- 参数 3 - 异常记录。 使用 .exr 显示它。
- 参数 4 - 上下文记录。 使用 .cxr 显示它。
- 测试层: 内存
- 停止 ID: SIZE_HEAP_UNEXPECTED_EXCEPTION
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
释放起始地址无效的内存块。
可能的原因如果程序调用 VirtualFree (MEM_RELEASE),其 lpAddress 参数不是 VirtualAlloc 或 VirtualAllocEx 函数在保留页面区域时返回的基址,则会生成此停止;要调试此停止:$ kb - 显示当前堆栈跟踪,即调用 VirtualFree。 原因可能是调用了 VirtualFree 的 DLL。
应用程序验证程序显示的信息- 参数 1 - 被释放内存块的地址。
- 参数 2 - 预期正确的内存块地址。
- 参数 3 - 未使用。
- 参数 4 - 未使用。
- 测试层: 内存
- 停止 ID: INVALID_FREEMEM_START_ADDRESS
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
取消映射起始地址无效的内存块。
可能的原因如果程序在调用 UnmapViewOfFile 时使用的 lpBaseAddress 参数与之前调用 MapViewOfFile 或 MapViewOfFileEx 函数返回的值不一致,则会生成此停止。 要调试此停止:$ kb - 显示当前堆栈跟踪,即正在调用 UnmapViewOfFile。 原因可能是调用 UnmapViewOfFile 的 DLL。
应用程序验证程序显示的信息- 参数 1 - 正在取消映射的内存块地址。
- 参数 2 - 预期正确的内存块地址。
- 参数 3 - 未使用。
- 参数 4 - 未使用。
- 测试层: 内存
- 停止 ID: INVALID_UNMAPVIEW_START_ADDRESS
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
线程池回调函数中出现意外异常。
可能的原因如果线程池线程中的回调函数引发异常,则会生成此停止。 要调试此停止:$ parameter1 可能对异常类型很重要。 例如,异常代码 C0000005 表示访问冲突。 $ .exr parameter2 - 显示异常信息。 $ .cxr parameter3 后跟 kb - 显示异常上下文信息。
应用程序验证程序显示的信息- 参数 1 - 异常代码
- 参数 2 - 异常记录。 使用 .exr 显示它。
- 参数 3 - 上下文记录。 使用 .cxr 显示它
- 参数 4 - 未使用
- 测试层: 内存
- 停止 ID: THREADPOOL_UNEXPECTED_EXCEPTION
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
不可执行内存中的代码
可能的原因如果应用程序尝试从一个不可执行或空闲的地址运行代码,则会生成此停止。 要调试此停止:$ u parameter2 - 用于反汇编原因代码;$ .exr parameter3 - 用于显示异常信息;$ .cxr parameter4 后跟 kb - 用于显示异常上下文信息和异常发生时的堆栈跟踪。
应用程序验证程序显示的信息- 参数 1 - 正在访问的地址
- 参数 2 - 执行无效访问的代码
- 参数 3 - 异常记录。 使用 .exr 显示它。
- 参数 4 - 上下文记录。 使用 .cxr 显示它。
- 测试层: 内存
- 停止 ID: THREADPOOL_UNEXPECTED_EXCEPTION_CODE
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
创建可执行堆。
可能的原因如果应用程序正在创建可执行堆,则会生成此停止。 这可能会带来安全风险。
应用程序验证程序显示的信息- 参数 1 - 未使用。
- 参数 2 - 未使用。
- 参数 3 - 未使用。
- 参数 4 - 未使用。
- 测试层: 内存
- 停止 ID: EXECUTABLE_HEAP
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
分配可执行内存。
可能的原因如果应用程序正在分配可执行内存,则会生成此停止。 这可能会带来安全风险。
应用程序验证程序显示的信息- 参数 1 - 调用方指定的页面保护。
- 参数 2 - 未使用。
- 参数 3 - 未使用。
- 参数 4 - 未使用。
- 测试层: 内存
- 停止 ID: EXECUTABLE_MEMORY
- 停止代码: 600NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
TLS 停止详细信息
卸载分配了未释放的 TLS 索引的 DLL。
可能的原因如果分配了 TLS 索引的 DLL 在释放该 TLS 索引之前被卸载,则会生成此停止。 要调试此停止:$ du parameter3 - 显示问题 DLL 的名称; $ .reload xxx.dll=parameter4 - 重新加载问题 DLL 的符号(如果需要)。 xxx.dll 是上述步骤中显示的 DLL 名称;$ u parameter2 - 反汇编分配 TLS 的代码。 这应该指向分配了 TLS 但忘记在 DLL 卸载前释放它的函数。
应用程序验证程序显示的信息- 参数 1 - TLS 索引
- 参数 2 - 分配此 TLS 索引的代码地址。
- 参数 3 - DLL 名称地址。 使用 du 将其转储。
- 参数 4 - DLL 基址。
- 测试层: TLS
- 停止 ID: TLS_LEAK
- 停止代码: 350NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
验证程序 TLS 结构损坏。
可能的原因如果用于存储线程 TLS 槽状态的内部校验结构已损坏,则会生成此停止。 这很可能是由于进程中的随机损坏造成的。
应用程序验证程序显示的信息- 参数 1 - TEB 地址。
- 参数 2 - 预期的 TEB 地址。
- 参数 3 - 线程 ID。
- 参数 4 - 预期的线程 ID。
- 测试层: TLS
- 停止 ID: CORRUPTED_TLS
- 停止代码: 350NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
使用无效的 TLS 索引。
可能的原因如果使用了无效的 TLS 索引,则会生成此停止。 在大多数情况下,这是因为调用 TlsFree 时代码仍在使用该索引所致。 下面是线程池线程的示例。 T1:Dll 加载和 TlsAlloc T1:队列回调 T1:跳过等待/取消回调 T1:TlsFree T2:回调运行并调用 TlsSetValue T1:Dll 卸载
应用程序验证程序显示的信息- 参数 1 - TLS 索引
- 参数 2 - 未使用。
- 参数 3 - 未使用。
- 参数 4 - 未使用。
- 测试层: TLS
- 停止 ID: INVALID_TLS_INDEX
- 停止代码: 350NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
线程池停止详细信息
此线程池线程的优先级已更改。
可能的原因如果线程返回线程池时优先级发生变化,则会生成此停止。
应用程序验证程序显示的信息- 格式: - 执行了回调 (%p) 的线程池线程 (%x) 的线程优先级已更改 (%i -> %i)
- 参数 1 - 回调函数。
- 参数 2 - 上下文。
- 参数 3 - 线程池对象分配堆栈跟踪,使用 dps 将其转储。
- 参数 4 - 当前优先级。
- 测试层: 线程池
- 停止 ID: INCONSISTENT_PRIORITY
- 停止代码: 700NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
此线程池线程的相关性已更改。
可能的原因如果线程关联性在返回线程池时发生变化,则会生成此停止。
应用程序验证程序显示的信息- 格式: - 执行回调 (%p) 的线程池线程 (%x) 的线程相关性掩码已更改 (%p -> %p)
- 参数 1 - 回调函数。
- 参数 2 - 上下文。
- 参数 3 - 线程池对象分配堆栈跟踪,使用 dps 将其转储。
- 参数 4 - 当前相关性。
- 测试层: 线程池
- 停止 ID: INCONSISTENT_AFFINITY_MASK
- 停止代码: 700NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
当前线程 msg 池中未处理的 msg。
可能的原因如果此线程池线程返回线程池时有未处理的消息,则会生成此停止。 这很危险,因为它将在完全不同的背景下进行处理。 请使用 !avrf -tp <Param4> 来查看发布到此主题的消息。
应用程序验证程序显示的信息- 格式: - 执行回调 (%p) 的线程 (%x) 有未读窗口消息 (%x: %x)
- 参数 1 - 回调函数。
- 参数 2 - 上下文。
- 参数 3 - 线程池对象分配堆栈跟踪,使用 dps 将其转储。
- 参数 4 - 线程池线程 ID。请使用 !avrf -tp <threadid> 来查看发布到此线程的消息。
- 测试层: 线程池
- 停止 ID: ORPHANED_THREAD_MESSAGE
- 停止代码: 700NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
属于当前线程的未关闭窗口。
可能的原因当线程池线程返回线程池时,如果有窗口保持活动状态,则会生成此停止。
应用程序验证程序显示的信息- 格式: - 执行了回调 (%p) 的线程池线程 (%x) 具有可接收消息的有效 hwnd (%x: %s)
- 参数 1 - 回调函数。
- 参数 2 - 上下文。
- 参数 3 - 线程池对象分配堆栈跟踪,使用 dps 将其转储。
- 参数 4 - 线程池线程 ID。
- 测试层: 线程池
- 停止 ID: ORPHANED_THREAD_WINDOW
- 停止代码: 700NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
线程池线程上的 ExitThread()。
可能的原因如果在线程池线程上调用 ExitThread,则会生成此停止,但这是禁止的,因为它会导致系统不稳定。 它会导致资源泄漏、冻结或 AV。
应用程序验证程序显示的信息- 参数 1 - 回调函数。
- 参数 2 - 上下文。
- 参数 3 - 线程池对象分配堆栈跟踪,使用 dps 将其转储。
- 参数 4 - 未使用。
- 测试层: 线程池
- 停止 ID: ILLEGAL_THREAD_EXIT
- 停止代码: 700NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
线程返回线程池线程时处于模拟状态。
可能的原因如果回调函数更改了线程令牌以模拟其他用户,并在将其返回线程池之前忘记重置令牌,则会生成此停止。
应用程序验证程序显示的信息- 参数 1 - 回调函数。
- 参数 2 - 上下文。
- 参数 3 - 线程池对象分配堆栈跟踪,使用 dps 将其转储。
- 参数 4 - 未使用。
- 测试层: 线程池
- 停止 ID: THREAD_IN_IMPERSONATION
- 停止代码: 700NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
需要持久线程的函数被调用。
可能的原因有些 Microsoft Windows API 需要在专用或持久线程内调用。 在线程池中,通常应避免使用线程本地存储和队列需要持久线程的异步调用,如 RegNotifyChangeKeyValue 函数。 但是,可以使用带有 WT_EXECUTEINPERSISTENTTHREAD 选项的 QueueUserWorkItem 来将此类函数排队到持久工作线程中。 调试器中的 kb 将显示调用方。
应用程序验证程序显示的信息- 参数 1 - 回调函数。
- 参数 2 - 上下文。
- 参数 3 - 线程池对象分配堆栈跟踪,使用 dps 将其转储。
- 参数 4 - 未使用。
- 测试层: 线程池
- 停止 ID: PERSISTED_THREAD_NEEDED
- 停止代码: 700NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
线程处于“脏”事务状态。
可能的原因如果回调函数忘记关闭或重置当前事务句柄,则会生成此停止。
应用程序验证程序显示的信息- 参数 1 - 回调函数。
- 参数 2 - 上下文。
- 参数 3 - 线程池对象分配堆栈跟踪,使用 dps 将其转储。
- 参数 4 - 事务句柄。
- 测试层: 线程池
- 停止 ID: DIRTY_TRANSACTION_CONTEXT
- 停止代码: 700NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
这种线程池状态下的 CoInit 和 CoUnInit 调用不平衡。
可能的原因如果回调函数调用 CoInit 和 CoUnInit 时出现不平衡,则会生成此停止。
应用程序验证程序显示的信息- 参数 1 - 回调函数。
- 参数 2 - 上下文。
- 参数 3 - 线程池对象分配堆栈跟踪,使用 dps 将其转储。
- 参数 4 - 平衡调用计数。
- 测试层: 线程池
- 停止 ID: DIRTY_COM_STATE
- 停止代码: 700NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
计时器对象的参数不一致。 创建计时器时指定 WT_EXECUTEONLYONCE 时,周期应为 0
可能的原因当使用 WT_EXECUTEONLYONCE 标志将计时器设置为只发出一次信号时,如果计时器发出信号的周期不为零,则会生成此停止
应用程序验证程序显示的信息- 参数 1 - 周期已指定。
- 参数 2 - 标志已指定。
- 参数 3 - 未使用。
- 参数 4 - 未使用。
- 测试层: 线程池
- 停止 ID: INCONSISTENT_TIMER_PARAMS
- 停止代码: 700NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
加载程序锁已被回调中的线程池线程保留。
可能的原因如果加载程序锁被保留在回调中,并且在线程返回线程池时未被释放,则会生成此停止。
应用程序验证程序显示的信息- 参数 1 - 回调函数。
- 参数 2 - 上下文。
- 参数 3 - 线程池对象分配堆栈跟踪,使用 dps 将其转储。
- 参数 4 - 未使用。
- 测试层: 线程池
- 停止 ID: LOADER_LOCK_HELD
- 停止代码: 700NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
首选语言由线程池线程在回调中设置。
可能的原因如果在回调中设置了首选语言,并且在线程返回线程池时没有被清除,则会生成此停止。
应用程序验证程序显示的信息- 参数 1 - 回调函数。
- 参数 2 - 上下文。
- 参数 3 - 线程池对象分配堆栈跟踪,使用 dps 将其转储。
- 参数 4 - 未使用。
- 测试层: 线程池
- 停止 ID: PREFERRED_LANGUAGES_SET
- 停止代码: 700NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
后台优先级由线程池线程在回调中设置。
可能的原因如果在回调中设置了后台优先级,且线程返回线程池时未禁用,则会生成此停止。
应用程序验证程序显示的信息- 参数 1 - 回调函数。
- 参数 2 - 上下文。
- 参数 3 - 线程池对象分配堆栈跟踪,使用 dps 将其转储。
- 参数 4 - 未使用。
- 测试层: 线程池
- 停止 ID: BACKGROUND_PRIORITY_SET
- 停止代码: 700NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是
在线程池线程上终止 Thread()。
可能的原因如果在线程池线程上调用 TerminateThread,则会生成此停止。 这是被禁止的,因为它会导致系统不稳定。 它会导致资源泄漏、冻结或 AV。
应用程序验证程序显示的信息- 参数 1 - 未使用。
- 参数 2 - 未使用。
- 参数 3 - 未使用。
- 参数 4 - 未使用。
- 测试层: 线程池
- 停止 ID: ILLEGAL_THREAD_TERMINATION
- 停止代码: 700NAN
- 严重性: 错误
- 一次性错误:
- 错误报告: 中断
- 记录到文件: 是
- 创建回溯: 是