2

我正在对始终运行良好的现有代码进行故障排除(它是 Jedi Windows 安全库中的终端服务器单元)。经过一番调查,问题部分已归结为对WTSOpenServer的调用:

  while true do
  begin
      hServer := WTSOpenServer(PChar('server'));
      WTSCloseServer(hServer);
      hServer := 0;
  end;

在一个随机(但很小)的数字或运行之后,我们会得到一个完全的应用程序崩溃,这使得调试变得很困难。以下是我已经尝试过的事情:

  • WTSOpenServer 不写入 pServername 参数(如 CreateProcessW)(实际上我检查了反汇编并复制了一份)
  • 将 nil 作为参数传递时,代码运行良好(因此可以与 localmachine 一起使用)。
  • 当使用远程服务器、localhost 甚至是虚拟服务器作为 pServerName 时,结果总是崩溃(在 Vista 和更高版本中,即使是无效的服务器名也会根据文档返回有效的句柄)。
  • 用 Delphi 2009 和 2010 测试
  • 相同的代码在 Visual Studio (c++) 中运行良好。
  • 检查了 Visual Studio 中的反汇编,并从 Delphi 调用了 asm 中的 WTSOpenServer(并将 Handle 类型更改为 C 中的指针):

    hModule := LoadLibrary('wtsapi32.dll');
    if hModule = 0 then
      Exit;
    
    WTSOpenServer := GetProcAddress(hModule, 'WTSOpenServerW');
    if WTSOpenServer = nil then
      Exit;
    
    while true do
    begin
      asm
        push dword ptr pServerName;
        call dword ptr WTSOpenServer;
        mov [hServer], eax;
      end;
    
      hServer := nil;
    end;
    
  • 忽略对 WTSCloseServer 的调用

  • 在 x64 和 x86 版本的 Windows 7 上测试代码
  • 使用外部调试器而不是 Delphi 一个(在这种情况下似乎运行良好,所以我的猜测是它是某种时间/线程/死锁问题)
  • 添加了 AddVectoredExceptionHandler然后我看到一个 EXCEPTION_ACCESS_VIOLATION 但堆栈似乎已损坏,EIP 为 1,因此无法确定它发生在哪里。

此时我不知道如何进一步解决此问题或找到解释。

4

1 回答 1

1

尝试在 FullDebugMode 下使用 FastMM 运行您的应用程序。它看起来更像是您/第 3 方库代码中的错误 - 可能的内存覆盖/缓冲区溢出(moslty like sth.GetMem 对于 UnicodeString/String 类似的操作来说太小了,它“有效”但迟早会崩溃/AV) .

在将大型应用程序迁移到 D2009 时,我遇到过几种类似的情况,在大多数情况下,这是由于假设 Char=1 字节。有时会发生非常奇怪的事情,但 FullDebugMode 总是有帮助。例外是 CreateProcessW,但它是已知/记录的行为。

使用 FullDebugMode 如果应用程序覆盖内存,那么当您释放它时,FastMM 会在分配它的位置为您提供异常,因此您可以轻松追踪此错误。它在分配的开始和结束时添加了一些字节,因此会知道它是否被覆盖。

我无法用新的/空的 VCL 项目重现它,您可以自己尝试(此循环运行约 5 分钟):

uses JwaWtsApi32;
procedure TForm7.FormCreate(Sender: TObject);
var
  hServer: DWORD;
begin
  while true do
  begin
      hServer := WTSOpenServer(PChar('server'));
      WTSCloseServer(hServer);
      hServer := 0;
  end;
end;
于 2010-01-06T19:56:47.893 回答