线程应用程序中的 Indy 错误!
当 TidHTTP 在 GET 后等待服务器的响应并且线程被终止时,我遇到了一些与 TidHTTP 相关的内存泄漏。
示例:
aThread = class(TThread)
private
FidHTTP :TidHTTP;
FCommand :String;
public
procedure Execute(); override;
constructor Create(aCommand :String); override;
procedure Disconnect;
end;
procedure aThread.Execute();
var response :String;
begin
response := FidHTTP.Get(FCommand);
end;
procedure aThread.Disconnect;
begin
if ((FidHTTP <> nil) and (FidHTTP.Connected)) then FidHTTP.IOHandler.CloseGracefully;
end;
constructor aThread.Create(aCommand :String); override;
begin
FCommand := aCommand;
inherited Create;
end;
当应用程序关闭时,我用此停止线程:
aThread.Disconnect;
aThread.Terminate;
aThread.Free;
我应该做什么来解决内存泄漏?
FastMM4 Log :
13 - 20 bytes: TIdThreadSafeInteger x 1
21 - 36 bytes: EAccessViolation x 1, TIdCriticalSection x 2
181 - 212 bytes: UnicodeString x 1
谢谢 :)
I've got some memories leak related to TidHTTP when it's waiting for the response of a server after a GET and that the thread is being terminated.
Example :
aThread = class(TThread)
private
FidHTTP :TidHTTP;
FCommand :String;
public
procedure Execute(); override;
constructor Create(aCommand :String); override;
procedure Disconnect;
end;
procedure aThread.Execute();
var response :String;
begin
response := FidHTTP.Get(FCommand);
end;
procedure aThread.Disconnect;
begin
if ((FidHTTP <> nil) and (FidHTTP.Connected)) then FidHTTP.IOHandler.CloseGracefully;
end;
constructor aThread.Create(aCommand :String); override;
begin
FCommand := aCommand;
inherited Create;
end;
I stop the thread with this when the application close :
aThread.Disconnect;
aThread.Terminate;
aThread.Free;
What should I do to solve the memories leaks ?
FastMM4 Log :
13 - 20 bytes: TIdThreadSafeInteger x 1
21 - 36 bytes: EAccessViolation x 1, TIdCriticalSection x 2
181 - 212 bytes: UnicodeString x 1
Thanks :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您应该
在销毁线程之前调用。这可确保线程正确终止。销毁线程而不终止它可能会导致执行方法中的访问冲突,从而导致 FastMM 显示内存泄漏。
编辑 考虑到问题可能是执行方法中的阻塞调用,您可能需要将 TIdHttp.ReadTimeOut 设置为合理的时间并定期检查线程是否终止。
You should call
before destroying the thread. This makes sure that the thread properly terminates. Destroying the thread without terminating it probably causes an access violation in the execute method, which results in the memory leaks displayed by FastMM.
EDIT Considering the fact that the problem might be the blocking call in your execute method, you might want to set TIdHttp.ReadTimeOut to a reasonable time and check for thread termination in regular intervals.
Indy 还会产生两到三个预期的内存泄漏,例如整数和临界区。但它们可能已按预期注册,也可能未注册。所以我不知道这些是不是你看到的。如果您运行代码 5 次,您会看到比现在更多的泄漏吗?
至于Smasher建议的WaitFor,在调用Free之前先调用。这不应该是必需的,也不应该是问题的原因,因为如果您检查 TThread 的析构函数,您将准确地看到已经完成的操作。
我真的不知道为什么你的泄漏报告中会出现访问冲突。但是,您正在从线程外部调用 Disconnect,而 Indy 组件正在您的线程中使用。不要这样做,从不同线程使用相同的非线程安全组件会带来麻烦。这可能会导致您的访问冲突泄漏。让线程本身执行对 Indy 组件的所有调用。
按照 Smasher 的建议减少 ReadTimeOut 是一个好主意,但可以确保您的应用程序不会阻塞太久。
Indy also produces two or three expected memory leaks, like the integer and the critical section. But they might or might not have been registered as expected. So I can't tell if these are the ones you see. If you would run your code 5 times, would you see more leakage than you are seeing now?
As for the WaitFor suggested by Smasher, to call before calling Free. This should not be needed, nor the cause of your problems, because if you check the destructor of TThread, you will see exactly that is already done.
Why you are getting an Access Violation in your leak report, I don't really know. However, you are calling Disconnect from outside of your thread, while the Indy component is in use in your thread. Don't do that, using the same non-thread-safe components from different threads is asking for trouble. This might cause your Access Violation leaking. Let the thread itself do ALL the calls to the Indy component.
Reducing the ReadTimeOut as suggested by Smasher is a good idea however to make sure your application doesn't block too long.