【发布时间】:2019-11-12 07:22:52
【问题描述】:
直到现在,我一直使用pixDestroy 来清理我的 JavaCPP/Leptonica 应用程序中的 PIX 对象。但是,我最近注意到一个奇怪的内存泄漏问题,我追踪到 Leptonica 函数在内部返回 pixClone 结果。我设法通过使用以下简单测试重现了该问题:
@Test
public void test() throws InterruptedException {
String pathImg = "...";
for (int i = 0; i < 100; i++) {
PIX img = pixRead(pathImg);
PIX clone = pixClone(img);
pixDestroy(clone);
pixDestroy(img);
}
Thread.sleep(10000);
}
当达到 Thread.sleep 时,Windows 任务管理器中的 RAM 内存使用量(不是堆大小)已增加到大约 1GB,并且在睡眠结束和测试完成之前不会释放。
查看pixClone 的文档,我们看到它实际上创建了现有 PIX 的句柄:
注意事项:
“克隆”只是现有像素的句柄 (ptr)。它的实现是因为 (a) 图像可能很大,因此成本很高 复制,并且 (b) 数据结构的额外句柄需要使用 避免双重释放和内存泄漏的简单策略。像素是 参考计数。 pixClone() 的副作用是增加 1 在引用计数中。
要使用的协议是: (a) 每当您想要现有图像的新句柄时,调用 pixClone(),它只会增加一个引用计数。 (二) 始终在所有句柄上调用 pixDestroy()。这会减少 ref 计数,使句柄为空,并且仅在 pixDestroy() 时销毁像素 已在所有句柄上调用。
如果我理解正确,我确实在所有句柄上调用 pixDestroy,所以引用计数应该达到零,因此 PIX 应该已经被销毁。显然,情况并非如此。有人可以告诉我我做错了什么吗?提前致谢!
【问题讨论】: