如何修复Raylib C++中生成商品地图时的内存泄漏函数?
内存泄漏与Double Free问题排查解决
我正在学习C++,用raylib基于Perlin Noise制作地图,需要为每种商品生成独立地图展示其可用省份,但运行时内存占用过高。用-fsanitizer检测后,定位到问题出在以下函数:
void renderGoodMap(World* w, Texture2D* tex) { vector<Good> g = w->getGoods(); int cols = w->get_num_cols(); int rows = w->get_num_rows(); for (uint i = 0; i < g.size(); i++) { byte* pixels = new byte[ rows * cols * 4 ]; bool* map = w->getGoodMapById(i); for (int j = 0; j < rows * cols; j++) { int index = j * 4; if (map[ j ]) { pixels[ index + 0 ] = (byte)255; pixels[ index + 1 ] = (byte)0; pixels[ index + 2 ] = (byte)0; pixels[ index + 3 ] = (byte)150; } else { pixels[ index + 0 ] = (byte)255; pixels[ index + 1 ] = (byte)255; pixels[ index + 2 ] = (byte)255; pixels[ index + 3 ] = (byte)100; } } Image img = { .data = pixels, .width = cols, .height = rows, .mipmaps = 1, .format = 7 }; ImageResizeNN(&img, cols * TILESIZE, rows * TILESIZE); tex[ i ] = LoadTextureFromImage(img); delete img.data; } }
我尝试用delete img.data释放内存,但如果同时删除pixels数组会触发double free错误,目前正在学习智能指针,想搞清楚问题根源和解决办法。
问题根源
- Double Free错误原因:
ImageResizeNN函数会重新分配内存存储缩放后的图像数据,并且会自动释放原img.data指向的内存(也就是你用new创建的pixels数组)。之后你再调用delete img.data,等于对已经被raylib释放的内存再次执行释放操作,直接触发double free。 - 内存占用过高原因:循环中每次
new的像素数组,如果没被正确释放,会造成内存泄漏;另外LoadTextureFromImage会把图像数据复制到GPU显存,但CPU端的图像数据如果没清理,也会持续占用内存。
解决方法
1. 停止手动释放img.data或pixels
raylib的图像操作函数会自行管理原图像数据的内存,不需要手动调用delete。
2. 用raylib官方函数释放图像内存
加载纹理后,必须调用UnloadImage来释放CPU端的图像数据,而不是手动delete,这是raylib内存管理的规范。
3. 用智能指针优化内存管理(可选)
用std::unique_ptr自动管理pixels数组的内存,避免因忘记释放或异常导致的泄漏,同时也能更安全地转移指针所有权。
修改后的代码:
#include <memory> void renderGoodMap(World* w, Texture2D* tex) { vector<Good> g = w->getGoods(); int cols = w->get_num_cols(); int rows = w->get_num_rows(); for (uint i = 0; i < g.size(); i++) { // 用unique_ptr自动管理像素数组,避免手动new/delete出错 std::unique_ptr<byte[]> pixels = std::make_unique<byte[]>(rows * cols * 4); bool* map = w->getGoodMapById(i); for (int j = 0; j < rows * cols; j++) { int index = j * 4; if (map[j]) { pixels[index + 0] = static_cast<byte>(255); pixels[index + 1] = static_cast<byte>(0); pixels[index + 2] = static_cast<byte>(0); pixels[index + 3] = static_cast<byte>(150); } else { pixels[index + 0] = static_cast<byte>(255); pixels[index + 1] = static_cast<byte>(255); pixels[index + 2] = static_cast<byte>(255); pixels[index + 3] = static_cast<byte>(100); } } Image img = { .data = pixels.release(), // 将指针所有权转移给Image .width = cols, .height = rows, .mipmaps = 1, .format = 7 }; ImageResizeNN(&img, cols * TILESIZE, rows * TILESIZE); tex[i] = LoadTextureFromImage(img); UnloadImage(img); // 用raylib函数释放所有CPU端图像内存 } }
内容的提问来源于stack exchange,提问作者Diogo Alves
相关产品推荐
相关产品推荐

