2

我最近从 Delphi 2010 升级到 Delphi 10.2 Tokyo 许多第 3 方库已经开始在调试模式下抛出异常,并且仅在调试模式下。最常见的错误是 $C0000005 一般保护故障。这些是我多年来一直在使用的库,并且非常完善。

这些是第 3 方库,我无权访问源代码。

这包括 jvm.dll 和 msxml 之类的东西

有什么线索吗?解决方法?这些问题是一致且持久的,并且有问题的应用程序在未调试时运行得非常愉快。

在我看到的每一种情况下,库都是动态链接的,而不是静态链接的。我怀疑这个问题与调试模式下的不同权限有关。

编辑:我跟踪了一个 DLL 调用,结果发现它正试图写入 DLL 的本地内存 DATA 或 BSS。在 Delphi 2010 中,它非常愉快地允许这样做。在东京,它会抛出 $C0000005 错误。我假设这是最新的 Delphi 调试器的错误或设置问题。

编辑 2:我已经设法提取了一个最小的应用程序来重现该问题。https://www.dropbox.com/s/uy8e9rw0qjxspie/testdll.zip?dl=0 下载包含一个最小的 32 位可执行文件 (testdll)。它静态链接到第 3 方 dll mirixafind.dll。这是一个旧的 dll,我无权访问源代码。如果您单独运行 testdll 或不进行调试,点击“Mirixa”按钮会在屏幕上打印一些行并停止。如果您运行 WITH 调试,它将失败并出现 $C0000005 错误,试图将字符串写入似乎是 dll 的 DATA(或可能的 BSS)段的一部分的内存部分。一位同事在单独的安装中复制了它。它不会发生在 Delphi 2010 中。

编辑 3:堆栈跟踪:

:757db78d user32.GetWindowTextA + 0x1d
:0068fbbf ; C:\Users\Robbie\Documents\Embarcadero\Studio\Projects\Win32\Debug\mirixafind.dll
:757e9275 ; C:\WINDOWS\SysWOW64\user32.dll
:757e757a user32.EnumWindows + 0x1a
:0068fca5 ; C:\Users\Robbie\Documents\Embarcadero\Studio\Projects\Win32\Debug\mirixafind.dll
:00691afa ; C:\Users\Robbie\Documents\Embarcadero\Studio\Projects\Win32\Debug\mirixafind.dll
:00690bcd ; C:\Users\Robbie\Documents\Embarcadero\Studio\Projects\Win32\Debug\mirixafind.dll
testdll1.TForm1.Button2Click($234B380)
Vcl.Controls.TControl.Click
Vcl.StdCtrls.TCustomButton.Click
Vcl.StdCtrls.TCustomButton.CNCommand(???)
Vcl.Controls.TControl.WndProc((48401, 3796, 1117908, 0, 3796, 0, (), 3796, 17, (), 0, 0, ()))
Vcl.Controls.TWinControl.WndProc((48401, 3796, 1117908, 0, 3796, 0, (), 3796, 17, (), 0, 0, ()))
Vcl.StdCtrls.TButtonControl.WndProc((48401, 3796, 1117908, 0, 3796, 0, (), 3796, 17, (), 0, 0, ()))
Vcl.Controls.TControl.Perform(???,???,1117908)
Vcl.Controls.DoControlMsg(???,(no value))
Vcl.Controls.TWinControl.WMCommand((273, (), 3796, 0, (), 1117908, 0))
Vcl.Controls.TControl.WndProc((273, 3796, 1117908, 0, 3796, 0, (), 3796, 17, (), 0, 0, ()))
Vcl.Controls.TWinControl.WndProc((273, 3796, 1117908, 0, 3796, 0, (), 3796, 17, (), 0, 0, ()))
Vcl.Controls.TWinControl.MainWndProc(???)
System.Classes.StdWndProc(1575384,273,3796,1117908)
:757ed2b3 user32.SetManipulationInputTarget + 0x53
:757ce88a ; C:\WINDOWS\SysWOW64\user32.dll
:757f764b ; C:\WINDOWS\SysWOW64\user32.dll
:757d0c00 ; C:\WINDOWS\SysWOW64\user32.dll
:6ccdd36f ; C:\WINDOWS\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.14393.953_none_89c2555adb023171\comctl32.dll
:6cced065 ; C:\WINDOWS\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.14393.953_none_89c2555adb023171\comctl32.dll
:757ed2b3 user32.SetManipulationInputTarget + 0x53
:757ce88a ; C:\WINDOWS\SysWOW64\user32.dll
:757cdf17 user32.CallWindowProcW + 0x97
Vcl.Controls.TWinControl.DefaultHandler(???)
:00521b5b TWinControl.DefaultHandler + $EB
:00521a4a TWinControl.WndProc + $5EE
:00536559 TButtonControl.WndProc + $71
:004c2b5a StdWndProc + $16
:757ed2b3 user32.SetManipulationInputTarget + 0x53
:757ce88a ; C:\WINDOWS\SysWOW64\user32.dll
:757ce1e4 ; C:\WINDOWS\SysWOW64\user32.dll
:757cdfa0 user32.DispatchMessageW + 0x10

First chance exception at $757DB78D. Exception class $C0000005 with message 'access violation at 0x757db78d: write of address 0x00974409'. Process testdll.exe (26036)

Module Load: MirixaFind.dll. No Debug Info. Base Address: $00970000. Process testdll.exe (26036)

dll 的 Tdump 提供以下信息:

Object table:
#   Name              VirtSize    RVA     PhysSize  Phys off  Flags   
--  --------          --------  --------  --------  --------  --------
01  CODE              00052714  00001000  00052800  00000400  60000020 [CER]
02  DATA              000013D8  00054000  00001400  00052C00  C0000040 [IRW]
03  BSS               00000B7D  00056000  00000000  00054000  C0000000 [RW]
04  .idata            00001F86  00057000  00002000  00054000  C0000040 [IRW]
05  .edata            0000139F  00059000  00001400  00056000  50000040 [IRS]
06  .reloc            0000588C  0005B000  00005A00  00057400  50000040 [IRS]
07  .rsrc             00004800  00061000  00004800  0005CE00  50000040 [IRS]

Key to section flags:
  C - contains code
  E - executable
  I - contains initialized data
  R - readable
  S - shareable
  W - writeable

据我所知,在这种情况下 0x00974409 应该是一个完全合法的地址。

4

3 回答 3

3

事实证明,我看到的是调试器捕获了一个在 dll 中处理的异常。

Tools-->Options-->Debugger Options-->Embarcadero Debuggers-->Native OS Exceptions-->32-bit windows OS Exceptions-->Access Violation ($C0000005) 设置为“由调试器处理”

在以前的 Delphi 版本中,这默认为“用户程序”(与所有其他本机操作系统异常一样)

它看起来比实际更糟,因为它发生在循环的中间,所以它不断被抛出......但如果我只是告诉 Delphi 忽略这个异常,它就会消失。(总台)

于 2017-05-16T23:35:56.693 回答
0

错误 5 是拒绝访问。

这可能是尝试写入 null(或前 64k 数据中的任何位置),或者(如您所料)它正在调用没有正确安全设置的 Win32 API 函数。

我想您已经尝试在管理员帐户下运行您的应用程序,看看它是否与此有关?

于 2017-05-09T10:26:02.437 回答
0

发布作为答案,以便代码格式正确。

因此,从堆栈跟踪看起来代码正在枚举所有窗口以获取窗口文本(可能是每个窗口的标题?)。很难理解,但是如果您可以在 0x0068fbbf 处转储程序集,您将看到传递给 GetWindowText 的参数。原型(下图)很难出错。

int WINAPI GetWindowText(_In_ HWND hWnd, _Out_ LPTSTR lpString, _In_ int nMaxCount);

我的猜测lpString是空的。

只需阅读 GetWindowText 上的文档:

将指定窗口标题栏(如果有)的文本复制到缓冲区中。如果指定的窗口是控件,则复制控件的文本。但是,GetWindowText 无法在另一个应用程序中检索控件的文本

我想知道您是否尝试在不属于您的应用程序上枚举 Windows?

于 2017-05-15T08:11:44.240 回答