Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot destroy THTTPReqResp component in a thread

I am having problems using SOAP in XE/XE2 from a thread. (I didn't test it with older Delphis.) A simple code that works in the main thread crashes while destroying the THTTPReqResp instance with Invalid pointer operation.

This is the complete program. The form contains only one button which triggers btnTestClick event:

unit Unit79;

interface

uses
  SysUtils, Forms, Classes, Controls, StdCtrls, ComObj,
  ActiveX, InvokeRegistry, SOAPHTTPTrans, Rio, SOAPHTTPClient;

type
  TForm79 = class(TForm)
    btnTest: TButton;
    procedure btnTestClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form79: TForm79;

implementation

{$R *.dfm}

procedure TForm79.btnTestClick(Sender: TObject);
begin
  TThread.CreateAnonymousThread(
    procedure
    var
      FHTTPReqResp: THTTPReqResp;
      FHTTPRIO: THTTPRIO;
    begin
      if CoInitializeEx(NIL, COINIT_MULTITHREADED or COINIT_SPEED_OVER_MEMORY) = S_OK then try
        FHTTPReqResp := THTTPReqResp.Create(nil);
        with FHTTPReqResp do begin
          Name := 'HTTPReqResp1';
          UseUTF8InHeader := True;
          InvokeOptions := [soIgnoreInvalidCerts, soAutoCheckAccessPointViaUDDI];
          WebNodeOptions := [];
        end;
        FHTTPRIO := THTTPRIO.Create(nil);
        with FHTTPRIO do begin
          Name := 'HTTPRIO1';
          HTTPWebNode := FHTTPReqResp;
        end;
        //
        FreeAndNil(FHTTPRIO);
        FreeAndNil(FHTTPReqResp); //<-- crashes here
      finally CoUninitialize; end;
    end
  ).Start;
end;

end.

The exception is raised in TObject.FreeInstance on the _FreeMem call.

procedure TObject.FreeInstance;
begin
  CleanupInstance;
  _FreeMem(Self);
end;

The call stack leading to this problem is

:75bab9bc KERNELBASE.RaiseException + 0x58 System.TObject.FreeInstance
System.ErrorAt(2,$4052E1) System.Error(reInvalidPtr)
System.TObject.FreeInstance System._ClassDestroy(???)
Soap.SOAPHTTPTrans.THTTPReqResp.Destroy System.TObject.Free
frmMain.TMainForm.btnTestClick$4934$ActRec.$0$Body
System.Classes.TAnonymousThread.Execute
System.Classes.ThreadProc($F83530) System.ThreadWrapper($F51050)
:76a4339a kernel32.BaseThreadInitThunk + 0x12 :77b59ef2
ntdll.RtlInitializeExceptionChain + 0x63 :77b59ec5
ntdll.RtlInitializeExceptionChain + 0x36

I have absolutely no idea what's going on, why _ClassDestroy is called at all and why the code crashes :( Can somebody please a) explain what I'm doing wrong and b) fix my code?

like image 391
gabr Avatar asked Jan 16 '12 19:01

gabr


1 Answers

"Invalid pointer operation" means you're freeing something that doesn't represent valid memory. That can sometimes indicate stack or heap corruption, but it more likely indicates that you're freeing something that has already been freed.

It's no surprise that _ClassDestroy is called. FHTTPReqResp is non-null, so when FreeAndNil calls Free on it, Free calls Destroy.

It would appear that your THTTPRIO object acquires ownership of the THTTPReqResp you give it. If that's the case, then the solution is simple: don't free it yourself.

like image 166
Rob Kennedy Avatar answered Oct 30 '22 00:10

Rob Kennedy