Delphi xe5 使用TIdHTTP和TIdSSLIOHandlerSocketOpenSSL的内存泄漏
我有以下课程Delphi xe5 使用TIdHTTP和TIdSSLIOHandlerSocketOpenSSL的内存泄漏,delphi-xe5,indy10,Delphi Xe5,Indy10,我有以下课程 type TMyDownload = class private FHttp: TIdHttp; function VerifyPeer(Certificate: TIdX509; AOk: Boolean; ADepth, AError: Integer): Boolean; public constructor Create(const ARootCertFile: string); destructor Destroy; overr
type
TMyDownload = class
private
FHttp: TIdHttp;
function VerifyPeer(Certificate: TIdX509; AOk: Boolean; ADepth, AError: Integer): Boolean;
public
constructor Create(const ARootCertFile: string);
destructor Destroy; override;
function Get(const URL: string; Stream: TStream): Integer;
end;
constructor TMyDownload.Create(const ARootCertFile: string);
begin
inherited Create;
FHttp := TIdHTTP.Create;
FHttp.Compressor := TIdCompressorZLib.Create(FHttp);
FHttp.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(FHttp);
FHttp.HandleRedirects := True;
FHttp.ProtocolVersion := pv1_1;
FHttp.ConnectTimeout := 10000;
FHttp.ReadTimeout := 10000;
FHttp.AllowCookies := True;
with TIdSSLIOHandlerSocketOpenSSL(FHttp.IOHandler) do
begin
OnVerifyPeer := VerifyPeer;
SSLOptions.Mode := sslmClient;
SSLOptions.Method := sslvTLSv1_2;
SSLOptions.RootCertFile := ARootCertFile;
SSLOptions.SSLVersions := [sslvTLSv1_2];
SSLOptions.VerifyMode := [sslvrfPeer, sslvrfFailIfNoPeerCert, sslvrfClientOnce];
SSLOptions.VerifyDepth := 5;
end;
end;
destructor TMyDownload.Destroy;
begin
FreeAndNil(FHttp);
inherited;
end;
function TMyDownload.Get(const URL: string; Stream: TStream): Integer;
begin
try
FHttp.Get(URL, Stream, [304]);
Exit(FHttp.ResponseCode);
except
LogException(ClassName, False, True);
Result := 500;
end;
end;
function TMyDownload.VerifyPeer(Certificate: TIdX509; AOk: Boolean; ADepth, AError: Integer): Boolean;
var
CurrentTime: TDateTime;
begin
if (ADepth = 0) then
begin
if AOk and (AError = 0) then
begin
CurrentTime := Now;
Result := (Pos('/CN=' + UpperCase(FHttp.URL.Host) + '/', '/' + UpperCase(Certificate.Subject.OneLine) + '/') <> 0)
and (CurrentTime >= Certificate.notBefore)
and (CurrentTime <= Certificate.notAfter);
end
else
Result := False;
end
else
Result := AOk and (AError = 0);
end;
上述代码构成了整个程序。如果运行3到5天,程序将耗尽内存(在Win32上消耗2+GB)。如果我禁用
SSLOptions.RootCertFile := ARootCertFile;
该程序运行良好,但缺点是必须接受不安全的链证书
是否有我遗漏的东西,有没有人能给我指出正确的方向我看不到这段代码中有任何会导致泄漏的东西。您是否使用Delphi的
ReportMemoryLeaksOnShutdown
检查是否报告了真正的泄漏?也许您正在经历内存碎片而不是泄漏?如果没有关于应用程序内存使用的更多信息,真的很难区分这种或那种方式。在旁注中,如果引发了EIdHTTPProtocolException
,您的Get()
方法应该返回FHttp.ResponseCode
。相信我,它确实泄漏了。如果禁用“SSLOptions.RootCertFile”行,它不会泄漏。重申一下,代码代表了整个程序,仅仅因为内存使用量随着时间的推移而增加并不一定意味着内存正在泄漏。碎片内存不是泄漏内存。你需要更深入地调试你的应用程序,以找出实际情况。你显示的不是全部代码,因为你没有显示每1分钟调用TMyDownload.Get()
的实际循环。但我刚刚做了一个测试,使用Indy 10的最新SVN版本和来自的最新OpenSSL 1.0.2o DLL,并完全按照您显示的方式运行代码(包括证书的使用),每500毫秒循环一次下载,内存使用在几分钟内保持稳定。因此,你的应用程序中的其他东西可能会泄漏/碎片内存,而你只是将其归因于Indy。
SSLOptions.RootCertFile := ARootCertFile;