【问题标题】:Access violation when loading dll加载dll时访问冲突
【发布时间】:2011-07-19 11:20:00
【问题描述】:

普通的 C 应用程序在 MSVC6 上可以正常编译,但在运行时会引发访问冲突。

在 WinDbg 中运行应用程序时,加载 rasadhlp.dll(Windows 文件)时出现 AV 错误。

问题:在加载 windows dll 时,什么可能导致访问冲突?

我习惯于使用各种 nixes 而不是 windows,所以我可能缺少一些非常明显的东西。

[...]
ModLoad: 77920000 77a13000   C:\WINDOWS\system32\SETUPAPI.dll
ModLoad: 76fc0000 76fc6000   C:\WINDOWS\system32\rasadhlp.dll
  (f38.a08): Access violation - code c0000005 (first chance)
  First chance exceptions are reported before any exception handling.
  This exception may be expected and handled.
  eax=00000000 ebx=00000000 ecx=00000000 edx=0049f8f0 esi=0049f8f0 edi=00000000
  eip=7c918fea esp=0012fbdc ebp=0012fc50 iopl=0         nv up ei ng nz na pe nc
  cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010286
  ntdll!RtlpWaitForCriticalSection+0x5b:
  7c918fea ff4010          inc     dword ptr [eax+10h]  ds:0023:00000010=????????
0:000> g
  (f38.a08): Access violation - code c0000005 (!!! second chance !!!)
  eax=00000000 ebx=00000000 ecx=00000000 edx=0049f8f0 esi=0049f8f0 edi=00000000
  eip=7c918fea esp=0012fbdc ebp=0012fc50 iopl=0         nv up ei ng nz na pe nc
  cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000286
  ntdll!RtlpWaitForCriticalSection+0x5b:
  7c918fea ff4010          inc     dword ptr [eax+10h]  ds:0023:00000010=????????

注意:该应用程序在win2k上编译,在XP上测试。 (由于各种奇怪的原因,现在无法更改...)

[编辑]:程序跟踪:

ntdll!RtlpWaitForCriticalSection+0x5b
ntdll!RtlEnterCriticalSection+0x46
msvcrt!vprintf+0x18
intl!libintl_vfprintf+0xa8
intl!libintl_fprintf+0x1f
image00400000+0x6239
MSCTF!DllGetClassObject+0x1de9
ntdll!RtlpNtMakeTemporaryKey+0x7ec8
ntdll!RtlInitializeSListHead+0x115c0
ntdll!iswdigit+0x339
ntdll!LdrGetProcedureAddress+0x4b
image00400000+0x626f4

[edit 2]:我知道异常首先被调试器捕获,这是完全正常的。您会在日志中注意到我手动跳过了第一次机会异常,并强制它进入我的程序。我想知道这种错误的根源,而不是处理方式。

【问题讨论】:

  • 你能跟踪你的程序的执行吗?崩溃是否发生在进入 main 之前?
  • 另外,您是使用静态运行时还是动态运行时编译程序?
  • 我偷偷怀疑您正在混合运行时的两个版本,这可能会导致一些有趣的问题。您应该尝试针对静态运行时编译程序
  • 嘿哈斯图昆。这听起来很合理。我认为这是静态链接,但由于这是继承代码,让我确定...
  • 这是环境问题,堆栈跟踪肯定不会指向您的代码。 msctf.dll 是一个危险信号,进入控制面板+区域和语言选项并禁用语言栏。或者让机器从第四层的窗户滑出。

标签: c windows visual-c++ dll access-violation


【解决方案1】:

在加载库时,RtlpWaitForCriticalSection 中的访问冲突通常是由库尝试在 DllMain 中使用 LoadLibrary 或 kernel32.dll 之外的代码引起的,因为操作系统在调用该例程时持有“加载器锁”。

【讨论】:

    【解决方案2】:

    Microsoft support - First and second chance exception handling

    使用 SEH 作为信号机制是一种常见的做法。一些 应用程序编程接口 (API) 注册异常 处理程序在预期的失败条件,预期 发生在下层。

    当引发异常时,处理程序可能会更正或忽略 条件而不是允许故障向上传播 中间层。这在复杂的环境中非常有用,例如 作为预计会出现部分故障的网络,但它不是 希望仅仅因为几个操作之一而使整个操作失败 可选部件失败。在这种情况下,可以这样处理异常 应用程序没有识别出异常 发生了。

    但是,如果正在调试应用程序,调试器会看到所有 程序之前的异常。这是之间的区别 第一次和第二次机会异常:调试器获得第一个 有机会看到异常(因此得名)。如果调试器允许 程序继续执行并且不处理异常, 程序将照常看到异常。如果程序没有 处理异常,调试器有第二次机会看到 例外。在后一种情况下,程序通常会崩溃,如果 调试器不存在。

    如果您不想在调试器中看到第一次机会异常, 您应该禁用特定的第一次机会异常处理 异常代码。否则,当第一次机会异常发生时,您 可能需要指示调试器将异常传递给 程序照常处理。

    【讨论】:

    • 我可以给你一个-1,没有理智的人会使用访问冲突进行内部信号传递。
    • 这同样可以被标记为不是答案。
    • 嗯,“访问冲突”是一种常见的“第一次机会异常”。当“调试器”收到正在运行的程序的异常时会产生此问题——程序产生异常,在程序处理它之前,调试器将收到“第一次机会异常”,然后,该异常应由程序本身。如果程序没有处理它,调试器将收到“第二次机会/最后一次机会异常”,并结束程序。我想微软的文章解释得很好。
    • @Stan:我知道第一个通常会被调试器捕获,您会在日志中注意到我手动跳过了第一个机会。我想知道的是为什么它首先发生,尤其是在加载 rasadhlp.dll 之后,它是一个 windows dll。访问违规也应该永远用作信号。这不是捕捉问题,而是起源问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多