2012-01-16 15 views
7

Mam problemy z używaniem SOAP w XE/XE2 z wątku. (Nie testowałem tego ze starszymi Delphis.) Prosty kod działający w głównej awarii wątków podczas niszczenia instancji THTTPReqResp z Invalid pointer operation.Nie można zniszczyć komponentu THTTPReqResp w wątku

To jest kompletny program. Formularz zawiera tylko jeden przycisk, który uruchamia zdarzenie btnTestClick:

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. 

Wyjątkiem jest podniesione w TObject.FreeInstance na wezwanie _FreeMem.

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

Stos wywołań prowadzi do tego problemu jest

: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 

mam absolutnie żadnego pojęcia, co się dzieje, dlaczego _ClassDestroy nazywa się w ogóle i dlatego kod wywala :(Może ktoś proszę a) wyjaśnić, co robię źle i b) naprawić mój kod?

+0

D2010 nie ma jeszcze CreateAnonymousThread. Próbuję teraz z anonimami. Bez awarii z nieanonimowym wątkiem. –

+0

Threading nie jest tu problemem (chyba). To samo zawiesza się w OmniThreadLibrary (w ten sposób znalazłem ten problem). – gabr

+3

Z dokumentacji THttprio "Gdy zostanie utworzony z parametrem zero (Delphi) lub NULL (C++), zostanie automatycznie zniszczony, gdy liczba odwołań spadnie do zera". Wyraźnie go uwalniasz. –

Odpowiedz

8

"Nieprawidłowe działanie wskaźnika" oznacza uwolnienie czegoś, co nie jest poprawną pamięcią. Może to czasami wskazywać na uszkodzenie stosu lub sterty, ale bardziej prawdopodobne jest, że zwalniasz coś, co zostało już uwolnione.

Nic dziwnego, że wywoływana jest nazwa _ClassDestroy. FHTTPReqResp ma wartość inną niż null, więc gdy FreeAndNil dzwoni pod numer Free, Free dzwoni Destroy.

Wygląda na to, że obiekt THTTPRIO przejmuje prawa własności do nadanego mu THTTPReqResp. Jeśli tak jest, to rozwiązanie jest proste: nie uwolnij go sam.

+3

Masz rację. Uwolnienie właśnie FHTTPRIO niszczy oba jako FastMM4 FullDebugMode potwierdź. Głupia architektura kodu, nigdy bym o tym nie pomyślał! – gabr

+0

Architektura SOAP jest niczym innym, jak tylko klinem pełnym "Yuck!" chwile. Spędziłem z nim rok. Moim najmniejszym ulubionym aspektem jest sposób, w jaki normalnie zależy od WinInet, który jest błędny i ma timeout/freeze-up w niektórych systemach Windows. Po przejściu do transportu HTTPRIO w trybie indygo tracisz losowe zawieszenie, ale ogólny spadek wydajności wynosi około 40%. Dobry wybór. –

+0

Dziękuję za tę odpowiedź. Mam problem z wyciekiem pamięci i mam nadzieję, że to rozwiązuje. –

Powiązane problemy