Valgrind能够检测OpenGL内存泄漏吗?

3

我正在测试一个OpenGL应用程序,有意不删除许多OpenGL结构以检查内存泄漏。

例如,我创建了一个多个着色器的数组,从未调用glDeleteShader()

然而,valgrind没有报告任何内存泄漏,

是因为valgrind无法检测到这些内存泄漏,还是因为有一些垃圾回收器在背后确保没有这样的泄漏发生?


2
着色器(shaders)据我所知存在于您的图形硬件或显示服务器上。valgrind只能检测到进程中的内存泄漏。如果您的进程发送OpenGL命令以创建五个着色器,并在此过程中释放了用于执行此操作的所有内存,则就该进程而言,所有进程内存都已被释放,您的进程不会泄漏内存。 - Sam Varshavchik
1
@Makogen 是的,可能是在GPU和/或驱动程序中。问题是Valgrind无法检测到它。 - user253751
有没有一款可以让我检查GPU内存泄漏的程序? - Makogan
不了解OpenGL库的内部工作方式,很可能会使用文件描述符通过内核与显卡通信,当文件描述符关闭时,内核会通知显卡释放与其关联的所有资源。这应该很容易测试。编写一个简单的程序来创建着色器,但不释放它们。编写一个简单的脚本来重复执行它。如果着色器资源没有被清理,显卡很快就会耗尽内存,并拒绝创建更多的着色器。 - Sam Varshavchik
驱动程序不知道除非你明确告诉它,否则你不会再次使用那些对象。我不是驱动程序编写者,但我相当确定这是上下文本地状态,应该在删除上下文或如果你不这样做,当操作系统终止你的进程时消失。 - Robinson
显示剩余2条评论
1个回答

6
然而valgrind未报告内存泄漏,这是因为Valgrind的默认配置将OpenGL从被分析对象中排除。这是由于一种简单的原因:大多数OpenGL实现会进行垃圾回收。当您调用glDelete...时,所有“外部”可访问的对象名称/ID都将与实际内部表示分离。

glDelete...调用之后,OpenGL实现可能需要把实际数据保留更长时间;例如可能仍有渲染命令正在引用已“删除”名称的对象。实际清理通常比“您”的glDelete...调用要晚得多。此外,大多数OpenGL实现实际上不会释放内存,而是将其保留以供新创建的名称循环使用。

总之,在典型的OpenGL实现中,即使在程序终止时一切都干净地整理了,Valgrind也会报告许多内存泄漏。因此它被列入黑名单。


1
那么,从内存的角度来看,不在应用程序结束时显式删除这些结构是可以的吗?这是一个好的做法吗? - Makogan
@Makogan:实际上,如果您确定进程即将终止,不释放任何内容是完全可以的。只需确保所有数据写入(离开进程)已被刷新和同步(以防数据丢失)。但除此之外,只需终止该进程。四处走动,释放所有内容,遍历每个析构函数就像在爆破队使用炸药和拆除球之前重新装修和粉刷房子一样。实际上,这可能会导致不必要的延迟,迫使操作系统分页交换出的内存。 - datenwolf
1
@Makogan:只是为了明确这一点:当一个进程终止时,操作系统(包括图形驱动程序)会确保进程分配的任何内容再次可用。实际上,操作系统所做的就是简单地丢弃已经进行过分配的信息。所有使用的资源几乎瞬间重新变得可用。 - datenwolf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接