树莓派4B上libcamera应用多帧内存存储崩溃问题求助
问题根源:默认拷贝构造/赋值的浅拷贝导致重复释放内存
你的代码崩溃的核心原因是ImageData类没有正确处理拷贝语义:
- C++编译器会自动生成默认的拷贝构造函数和赋值运算符,这些默认实现会浅拷贝所有成员变量,包括
buffer指针。 - 当
imageBuffer存储多帧时,vector可能因容量不足触发扩容,此时会对现有ImageData对象进行拷贝。多个对象会共享同一个buffer指针,当这些对象被析构(比如扩容时旧内存被释放),会多次调用delete[] buffer,触发double free错误,导致程序崩溃。 - 单帧存储时vector无需扩容,仅存在一个
ImageData对象,析构时仅释放一次内存,因此不会出现问题。
修复方案
方案1:禁用拷贝,显式实现移动语义(推荐,适配你的现有代码)
通过禁用拷贝构造和赋值运算符,强制使用移动语义,确保每个内存块仅被一个ImageData对象拥有:
class ImageData { public: ImageData(std::vector<libcamera::Span<uint8_t>> m, StreamInfo i, libcamera::ControlList met, std::string fil, std::string cam) : mem(m), info(i), metadata(met), filename(fil), cam_name(cam), buffer(new uint8_t[mem[0].size_bytes()]) {} ~ImageData() { delete[] buffer; } // 禁用拷贝构造和赋值,避免浅拷贝 ImageData(const ImageData&) = delete; ImageData& operator=(const ImageData&) = delete; // 显式实现移动构造,转移内存所有权 ImageData(ImageData&& other) noexcept : mem(std::move(other.mem)), info(std::move(other.info)), metadata(std::move(other.metadata)), filename(std::move(other.filename)), cam_name(std::move(other.cam_name)), buffer(other.buffer) { other.buffer = nullptr; // 清空原对象指针,避免析构时重复释放 } // 显式实现移动赋值 ImageData& operator=(ImageData&& other) noexcept { if (this != &other) { delete[] buffer; // 释放当前对象的旧内存 // 转移所有成员的所有权 mem = std::move(other.mem); info = std::move(other.info); metadata = std::move(other.metadata); filename = std::move(other.filename); cam_name = std::move(other.cam_name); buffer = other.buffer; other.buffer = nullptr; } return *this; } std::vector<libcamera::Span<uint8_t>> mem; StreamInfo info; libcamera::ControlList metadata; std::string filename; std::string cam_name; uint8_t* buffer; };
方案2:改用智能指针管理内存(更简洁,减少手动内存操作)
使用std::unique_ptr自动管理堆内存,它默认禁用拷贝、支持移动,无需手动编写析构和移动函数:
#include <memory> class ImageData { public: ImageData(std::vector<libcamera::Span<uint8_t>> m, StreamInfo i, libcamera::ControlList met, std::string fil, std::string cam) : mem(m), info(i), metadata(met), filename(fil), cam_name(cam), buffer(std::make_unique<uint8_t[]>(mem[0].size_bytes())) {} // 无需手动编写析构函数,unique_ptr会自动释放内存 std::vector<libcamera::Span<uint8_t>> mem; StreamInfo info; libcamera::ControlList metadata; std::string filename; std::string cam_name; std::unique_ptr<uint8_t[]> buffer; // 替换原始指针为智能指针 };
额外检查项
为避免其他潜在问题,建议在ImageData构造函数中添加mem非空判断:
if (mem.empty()) { throw std::invalid_argument("ImageData: mem vector cannot be empty"); }
内容的提问来源于stack exchange,提问作者Too Long Din't Read
相关产品推荐
相关产品推荐

