Full source of example with same problem
我已将所有内容移至单个EXE
var SenderInstance: AutoGeneratedWebserviceUnit.Sender;
...
procedure TForm1.FormCreate(Sender: TObject);
begin
SenderInstance := AutoGeneratedWebserviceUnit.GetSender(False, 'http://invalid_URL'); // => there is no exception here
end;
...
procedure TForm1.Button1Click(Sender: TObject);
var
req: AutoGeneratedWebserviceUnit.Request;
res: AutoGeneratedWebserviceUnit.Response;
begin
try
req := Request.Create;
try
with req do
begin
ID := 0;
param := 'trash';
end;
res := SenderInstance.Request('Login', 'Pass', req); // => ESOAPHTTPException + EAccesViolation !
ShowMessage(res.status);
finally
req.Free;
res.Free; // ### MOST POSSIBLE PROBLEM CAUSE ###
end;
except
on E: Exception do
ShowMessage(E.Message);
end;
end;
我理解ESOAPHTTPException,但AV?为什么? ...
提出ESOAPHTTPException后会发生奇怪的事情...... 我认为有一些类似于内存泄漏的东西,我无法弄清楚,或者我做了一些非常愚蠢的事情......
任何设置?也许我忘记了什么?
我找到了一些东西 关于" res.Free;"在try / finally块里面的行 禁用此行不会导致AV 但Assigned(req)返回True Assigned(res)也返回True ...
什么......?
答案 0 :(得分:2)
导致AV的问题在于try..finally
事件处理程序中的Button1Click
子句。
您正试图释放res
变量(响应),其中未尚未分配任何内容,因为对Request
方法的调用失败并出现异常。这意味着它包含垃圾,并且通过调用res.Free
您正在访问您不应该访问的内存位置,这可能会引发几乎任何类型的奇怪错误。
要解决此问题,请在输入nil
之前将res设置为try..finally
,并在致电res.Free
之前检查是否已分配。
另一方面,这是因为res
是本地变量。如果它是类的实例的成员,编译器会自动为其分配nil
值。
<强>更新强>
正如@RobKennedy所说,使用嵌套 try..finally
块比使用nil
更好,因为我第一次告诉你(如果有一些析构函数可能会导致问题)失败)。
所以你会做以下事情:
req := Request.Create;
try
req.ID := 0;
req.param := 'trash';
res := SenderInstance.Request('Login', 'Pass', req);
try
ShowMessage(res.status);
finally
res.Free;
end;
finally
req.Free;
end;