使用glCallList创建3D对象出现内存泄漏,系统冻结求助
问题分析与解决方案
兄弟,我一眼就揪出你内存持续占用甚至冻结系统的原因了——你只清空了vector容器里的指针,但那些用new动态分配的ObjCoordinate和ObjFace对象根本没被释放!
问题根源
vector里存储的是指向堆内存对象的指针,调用vertex.clear()、faces.clear()这类操作,只是把指针从容器中移除,并不会自动释放指针指向的堆内存。这些被遗忘的对象会一直占用系统内存,每次调用drawObject()都会新增一批无法回收的内存,日积月累直接把系统内存榨干,最终导致冻结。
至于valgrind没查出异常,大概率是因为程序没正常退出(系统冻结后强制终止),valgrind没机会完整收集内存泄漏信息;或者你没有覆盖到所有代码路径的检查。
修复方案
给你两种靠谱的修复方式,按需选择:
1. 手动释放裸指针(最直接的临时修复)
在清空vector之前,遍历容器里的每个指针,手动调用delete释放对应的堆内存:
void MyClass::drawObject() { glPushMatrix(); std::vector<ObjCoordinate *> vertex; std::vector<ObjFace *> faces; std::vector<ObjCoordinate *> normals; // ... 你的顶点、面、法线初始化代码 ... // 先处理显示列表逻辑(假设你这里有glNewList/glEndList代码) // glNewList(...); // ... 绘制逻辑 ... // glEndList(); // 手动释放所有动态分配的对象 for (auto coord : vertex) { delete coord; } vertex.clear(); for (auto face : faces) { delete face; } faces.clear(); for (auto norm : normals) { delete norm; } normals.clear(); glPopMatrix(); }
2. 使用智能指针(更安全的长期方案)
用C++的智能指针替代裸指针,让容器自动管理内存,彻底避免忘记释放的问题。推荐用std::unique_ptr,它会在指针离开作用域时自动释放对应的对象:
#include <memory> // 记得包含头文件 void MyClass::drawObject() { glPushMatrix(); std::vector<std::unique_ptr<ObjCoordinate>> vertex; std::vector<std::unique_ptr<ObjFace>> faces; std::vector<std::unique_ptr<ObjCoordinate>> normals; // 用make_unique创建对象,不需要手动new vertex.push_back(std::make_unique<ObjCoordinate>(-1.30287, -1.44034, 0.216688)); vertex.push_back(std::make_unique<ObjCoordinate>(-1.27961, -1.50539, 0.072052)); // ... 其他顶点、面、法线的初始化代码同理 ... // ... 显示列表绘制逻辑 ... // 不需要手动delete!vector销毁或clear时,智能指针会自动释放内存 vertex.clear(); faces.clear(); normals.clear(); glPopMatrix(); }
额外提醒
另外要确认你的glCallList使用逻辑:如果创建显示列表时,OpenGL已经把顶点数据复制到显存中,那CPU端的这些对象释放后不会影响显示效果,完全没问题。你当前的内存问题完全是CPU端堆内存泄漏导致的,和OpenGL显存管理无关。
内容的提问来源于stack exchange,提问作者Kyu96
相关产品推荐
相关产品推荐

