2012-01-16 7 views
7

Tôi gặp sự cố khi sử dụng SOAP trong XE/XE2 từ một chuỗi. (Tôi đã không kiểm tra nó với Delphis cũ hơn.) Một mã đơn giản hoạt động trong các lỗi chính trong khi phá hủy cá thể THTTPReqResp với Invalid pointer operation.Không thể hủy thành phần THTTPReqResp trong một chủ đề

Đây là chương trình hoàn chỉnh. Biểu mẫu chỉ chứa một nút kích hoạt sự kiện 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. 

Ngoại lệ được nêu ra trong TObject.Miễn phí trong cuộc gọi _FreeMem.

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

Cuộc gọi chồng dẫn đến vấn đề này là

: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 

Tôi hoàn toàn không có ý tưởng những gì đang xảy ra, tại sao _ClassDestroy được gọi là chút nào và lý do tại sao mã treo :(Can ai đó xin vui lòng a) giải thích những gì tôi đang làm sai và b) sửa mã của tôi?

+0

D2010 chưa có CreateAnonymousThread. Đang cố gắng không ẩn danh ngay bây giờ. Không có sự cố với chuỗi không ẩn danh. –

+0

Luồng không phải là vấn đề ở đây (tôi nghĩ). Nó bị treo cùng với OmniThreadLibrary (đó là cách tôi tìm thấy vấn đề này). – gabr

+3

Từ tài liệu của THttprio "Khi nó được tạo với tham số nil (Delphi) hoặc NULL (C++), nó sẽ tự động hủy khi số tham chiếu giảm xuống 0". Bạn đang giải phóng nó một cách rõ ràng. –

Trả lời

8

"Thao tác con trỏ không hợp lệ" có nghĩa là bạn đang giải phóng thứ gì đó không đại diện cho bộ nhớ hợp lệ. Điều đó đôi khi có thể cho thấy sự tham nhũng đống hoặc đống, nhưng nó có nhiều khả năng chỉ ra rằng bạn đang giải phóng một cái gì đó đã được giải phóng.

Không có gì ngạc nhiên khi gọi _ClassDestroy. FHTTPReqResp không phải là số không, do đó, khi FreeAndNil gọi Free trên đó, Free gọi Destroy.

Có vẻ như đối tượng THTTPRIO của bạn có được quyền sở hữu của số THTTPReqResp mà bạn cung cấp. Nếu đúng như vậy, thì giải pháp rất đơn giản: đừng tự giải phóng nó.

+3

Bạn chính xác. Giải phóng chỉ FHTTPRIO phá hủy cả hai như FastMM4 FullDebugMode xác nhận. Kiến trúc mã ngu ngốc, tôi sẽ không bao giờ nghĩ về điều đó! – gabr

+0

Kiến trúc SOAP không là gì ngoài việc chứa đầy "Yuck!" khoảnh khắc. Tôi đã dành một năm làm việc với nó. Khía cạnh yêu thích nhất của tôi về nó là cách nó thường phụ thuộc vào WinInet, đó là lỗi và có thời gian chờ/đóng băng trên một số hệ thống Windows. Khi bạn chuyển sang chế độ vận chuyển HTTPRIO dựa trên indy, bạn sẽ mất đi sự đóng băng ngẫu nhiên, nhưng bạn sẽ giảm hiệu suất khoảng 40%. Lựa chọn tốt. –

+0

Cảm ơn câu trả lời này. Tôi đang gặp vấn đề rò rỉ bộ nhớ và hy vọng điều này sẽ giải quyết được vấn đề. –