2012-01-16 10 views
7

Tengo problemas utilizando SOAP en XE/XE2 de un hilo. (No lo probé con Delphis antiguo). Un código simple que funciona en el hilo principal se bloquea al destruir la instancia THTTPReqResp con Invalid pointer operation.no puede destruir componente THTTPReqResp en un hilo

Este es el programa completo. El formulario contiene sólo un botón que desencadena evento 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. 

La excepción se lanza en TObject.FreeInstance en la llamada _FreeMem.

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

La pila de llamadas que conduce a este problema es

: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 

no tengo absolutamente ninguna idea de lo que está pasando, por qué _ClassDestroy se llama en absoluto y por qué el código se bloquea :(Puede alguien por favor a) explicar lo que estoy haciendo mal yb) arreglar mi código?

+0

D2010 no tiene CreateAnonymousThread todavía. Probando con no anónimo ahora. No se bloquea con un hilo no anónimo. –

+0

Enhebrar no es un problema aquí (creo). Se bloquea lo mismo con OmniThreadLibrary (que fue la forma en que encontré este problema). – gabr

+3

De la documentación de THttprio "Cuando se crea con un parámetro nil (Delphi) o NULL (C++), se autodestruirá cuando el recuento de referencias caiga a cero". Lo estás liberando explícitamente. –

Respuesta

8

"operación de puntero no válido" significa que está liberando algo que no representa una memoria válida. A veces, esto puede indicar una pila o corrupción de montón, pero es más probable que indique que está liberando algo que ya se ha liberado.

No es de extrañar que se llama _ClassDestroy. FHTTPReqResp es no nulo, por lo que cuando FreeAndNil llamadas Free en él, Free llamadas Destroy.

Parece que su objeto THTTPRIO adquiere la propiedad del THTTPReqResp que le da. Si ese es el caso, entonces la solución es simple: no la liberes tú mismo.

+3

Estás en lo correcto. Liberar solo FHTTPRIO destruye ambos como confirmación FastMM4 FullDebugMode. ¡Arquitectura de código estúpida, nunca pensaría en eso! – gabr

+0

La arquitectura SOAP no es más que un montón de "¡Yuck!" momentos. Pasé un año trabajando con eso. Mi aspecto menos favorito es la forma en que normalmente depende de WinInet, que tiene errores y tiene tiempos de espera/congelaciones en algunos sistemas de Windows. Cuando se cambia al transporte HTTPRIO basado en indy, se pierden las congelaciones aleatorias, pero se obtiene una disminución general del rendimiento de aproximadamente 40%. Buena eleccion. –

+0

Gracias por esta respuesta. Estoy teniendo un problema de pérdida de memoria y espero que esto lo resuelva. –

Cuestiones relacionadas