代码之家  ›  专栏  ›  技术社区  ›  MB.

Delphi TThread.CurrentThread和EAccessViolation-这是一个Bug还是我的无能。。?

  •  11
  • MB.  · 技术社区  · 16 年前

    在Delphi 2009中,我发现每当我在应用程序中使用TThread.CurrentThread时,当应用程序关闭时,我都会收到如下错误消息:

    Exception EAccessViolation in module ntdll.dll at 0003DBBA.
    Access violation at address 7799DBBA in module 'ntdll.dll'.  Write of
    address 00000014.
    

    procedure TForm1.Button1Click(Sender: TObject);
    begin
      TThread.CurrentThread;
    end;
    

    在我的Vista机器和XP机器上,如果我

    所以我想知道这是否是一个bug,但同时我认为我很可能根本不了解在Delphi中如何使用TThreads的一些非常基本的内容。恐怕我是个德尔福新手。

    这样使用TThread.CurrentThread是否有明显的问题?


    更新:正如Fran§ois在下面指出的,这实际上是Delphi 2009目前的一个bug-您可以 vote for it here


    4 回复  |  直到 15 年前
        1
  •  15
  •   Francesca    16 年前

    不幸的是,它似乎是一个与类单元中的finalization部分的调用顺序相关联的bug:

    DoneThreadSynchronization ThreadLock
    FreeExternalThreads 要销毁调用时刚创建的线程对象 CurrentThread
    这要求ThreadLock在调用中已初始化
    EnterCriticalSection(ThreadLock) 在里面 TThread.RemoveQueuedEvents

    使现代化 :
    现在有一个 QC report

        2
  •  12
  •   gabr    15 年前

    在CodeGear发布修复之前,您可以使用下面的补丁。将其保存到独立单元中,并在程序中的任何位置使用它。我也会尝试将其添加到QC中。

    此版本适用于D2009(原件)、更新1和更新2。

    { Fix Delphi 2009's invalid finalization order in Classes.pas.
      Written by Primoz Gabrijelcic, http://gp.17slon.com.
      No rights reserved - released to public domain.
    }
    unit FixD2009Classes;
    
    interface
    
    implementation
    
    uses
      Windows,
      SysUtils,
      Classes;
    
    type
      TCode = array [0..109] of byte;
    
    {$WARN SYMBOL_PLATFORM OFF}
    
    procedure PatchClasses;
    {$IFDEF ConditionalExpressions}
    {$IF RTLVersion = 20}
    var
      i         : integer;
      oldProtect: cardinal;
      pCode     : ^TCode;
      tmp       : DWORD;
    const
      COffsets_Call: array [1..12] of integer = (0, 15, 24, 34, 49, 59, 69, 79, 89, 94, 99, 109);
      COffset_UnRegisterModuleClasses = 106;
      COffset_DoneThreadSynchronization = 94;
      COffset_FreeExternalThreads = 99;
      CCallDelta = COffset_FreeExternalThreads - COffset_DoneThreadSynchronization;
    {$IFEND}
    {$ENDIF}
    begin
    {$IFDEF ConditionalExpressions}
    {$IF RTLVersion = 20}
      pCode := pointer(cardinal(@TStreamReader.ReadToEnd) + COffset_UnRegisterModuleClasses);
      Win32Check(VirtualProtect(pCode, COffsets_Call[High(COffsets_Call)], PAGE_READWRITE, oldProtect));
      try
        for i := Low(COffsets_Call) to High(COffsets_Call) do
          if pCode^[COffsets_Call[i]] <> $E8 then
            raise Exception.Create('Unexpected version of Classes - cannot patch');
        tmp := PDword(@pCode^[COffset_DoneThreadSynchronization+1])^;
        PDword(@pCode^[COffset_DoneThreadSynchronization+1])^ :=
          PDword(@pCode^[COffset_FreeExternalThreads+1])^ + CCallDelta;
        PDword(@pCode^[COffset_FreeExternalThreads+1])^ := tmp - CCallDelta;
      finally VirtualProtect(pCode, COffsets_Call[High(COffsets_Call)], oldProtect, oldProtect); end;
    {$IFEND}
    {$ENDIF}
    end;
    
    initialization
      PatchClasses;
    end.
    
        3
  •  5
  •   gabr    15 年前

    { Fix Delphi 2009's invalid finalization order in Classes.pas.
      Written by Primoz Gabrijelcic, http://gp.17slon.com.
      No rights reserved - released to public domain.
    
      D2009 update 3 only.
    }
    unit FixD2009Classes;
    
    interface
    
    implementation
    
    uses
      Windows,
      SysUtils,
      Classes;
    
    type
      TCode = array [0..144] of byte;
    
    {$WARN SYMBOL_PLATFORM OFF}
    
    procedure PatchClasses;
    {$IFDEF ConditionalExpressions}
    {$IF RTLVersion = 20}
    var
      i         : integer;
      oldProtect: cardinal;
      pCode     : ^TCode;
      tmp       : DWORD;
    const
      COffsets_Call: array [1..12] of integer = (0, 15, 24, 42, 47, 58, 73, 91, 101, 111, 134, 139);
      COffset_UnRegisterModuleClasses = 107;
      COffset_DoneThreadSynchronization = 134;
      COffset_FreeExternalThreads = 139;
      CCallDelta = COffset_FreeExternalThreads - COffset_DoneThreadSynchronization;
    {$IFEND}
    {$ENDIF}
    begin
    {$IFDEF ConditionalExpressions}
    {$IF RTLVersion = 20}
      pCode := pointer(cardinal(@TStreamReader.ReadToEnd) + COffset_UnRegisterModuleClasses);
      Win32Check(VirtualProtect(pCode, COffsets_Call[High(COffsets_Call)], PAGE_READWRITE, oldProtect));
      try
        for i := Low(COffsets_Call) to High(COffsets_Call) do
          if pCode^[COffsets_Call[i]] <> $E8 then
            raise Exception.Create('Unexpected version of Classes - cannot patch');
        tmp := PDword(@pCode^[COffset_DoneThreadSynchronization+1])^;
        PDword(@pCode^[COffset_DoneThreadSynchronization+1])^ :=
          PDword(@pCode^[COffset_FreeExternalThreads+1])^ + CCallDelta;
        PDword(@pCode^[COffset_FreeExternalThreads+1])^ := tmp - CCallDelta;
      finally VirtualProtect(pCode, COffsets_Call[High(COffsets_Call)], oldProtect, oldProtect); end;
    {$IFEND}
    {$ENDIF}
    end;
    
    initialization
      PatchClasses;
    end.
    
        4
  •  0
  •   Toon Krijthe    16 年前

    我认为CurrentThread是在2009年(或2007年)添加的。我有2006年在家。但您确定它是类属性吗?

    推荐文章