You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

堆上用new分配数组后赋值给shared_ptr,如何释放T* blob数据?

问题:如何正确释放DNA_ImageBlob中std::shared_ptr管理的数组内存

在DNA_ImageBlob类中,通过new[]分配了一块T类型的数组,随后将该数组指针赋值给std::shared_ptr<T>类型的成员data_,需要确保这块内存被正确释放。

现有代码问题分析

先看当前的实现代码:

DNA_ImageBlob::Reset方法

template <class T>
void DNA_ImageBlob<T>::Reset(int h, int w, int c)
{
    SetWidth(w);
    SetHeight(h);
    SetDepth(c);
    T *blob = alocData(h, w, c);
    data_ = std::make_shared<T>(blob); // 错误:此处会导致内存释放异常
    compressed_ = false;
}

alocData方法

template <class T>
T *DNA_ImageBlob<T>::alocData(unsigned int h, unsigned int w, unsigned int d)
{
    if (w * h * d == 0)
    {
        return nullptr;
    }
    T *blob = new T[w * h * d]; // 使用new[]分配数组
    return blob;
}

DNA_Mask构造函数示例

DNA_Mask::DNA_Mask(int id, int xSize, int ySize, int zSize)
        : DNA_BinaryImageBlob(xSize, ySize, zSize)
{
    mID = id;
    height_ = xSize;
    width_ = ySize;
    depth_ = zSize;
    data_ = std::shared_ptr<BinaryType>(this->alocData(height_, width_, depth_)); // 同样存在释放错误
}

当前代码的核心问题:

  • alocData用new[]分配数组,但std::shared_ptr默认的删除器是调用delete,而非delete[],这会导致未定义行为(内存泄漏、程序崩溃等)。
  • std::make_shared<T>(blob)的用法完全错误:它会把blob当作单个T对象的指针来构造shared_ptr,实际blob是数组首地址,这不仅会导致释放方式错误,还会在构造时错误地解引用数组指针(如果T有构造函数的话)。

正确的解决方案

方案1:给std::shared_ptr指定自定义删除器

既然用new[]分配数组,就必须用delete[]释放,因此需要给shared_ptr传入一个自定义删除器,告诉它用delete[]来清理内存。

修改Reset方法:

template <class T>
void DNA_ImageBlob<T>::Reset(int h, int w, int c)
{
    SetWidth(w);
    SetHeight(h);
    SetDepth(c);
    T *blob = alocData(h, w, c);
    // 传入lambda作为删除器,使用delete[]释放数组
    data_ = std::shared_ptr<T>(blob, [](T* ptr) {
        delete[] ptr;
    });
    compressed_ = false;
}

修改DNA_Mask构造函数:

DNA_Mask::DNA_Mask(int id, int xSize, int ySize, int zSize)
        : DNA_BinaryImageBlob(xSize, ySize, zSize)
{
    mID = id;
    height_ = xSize;
    width_ = ySize;
    depth_ = zSize;
    BinaryType* blob = this->alocData(height_, width_, depth_);
    data_ = std::shared_ptr<BinaryType>(blob, [](BinaryType* ptr) {
        delete[] ptr;
    });
}

方案2:用std::vector<T>替代手动内存管理(更推荐)

手动分配数组并配合shared_ptr容易出错,更安全的做法是用std::vector<T>来管理数组内存,它会自动调用delete[]释放内存,同时可以通过data()方法获取底层数组指针,完全兼容现有逻辑。

可以将data_的类型从std::shared_ptr<T>改为std::shared_ptr<std::vector<T>>,或者直接用std::vector<T>(如果不需要跨对象共享所有权的话)。

修改示例:

// 调整DNA_ImageBlob的成员类型
template <class T>
class DNA_ImageBlob {
private:
    std::shared_ptr<std::vector<T>> data_;
    // ...其他成员
};

template <class T>
void DNA_ImageBlob<T>::Reset(int h, int w, int c)
{
    SetWidth(w);
    SetHeight(h);
    SetDepth(c);
    size_t total = static_cast<size_t>(h) * w * c;
    data_ = std::make_shared<std::vector<T>>(total); // vector自动分配内存
    compressed_ = false;
}

// 获取底层数组指针的方法(如果需要对外提供)
template <class T>
T* DNA_ImageBlob<T>::GetData() {
    return data_->data();
}

这种方式的优势:

  • 完全避免手动内存管理的错误,vector自动处理内存分配和释放。
  • 支持动态调整大小,自带边界检查(如果使用at()访问的话),更安全。
  • shared_ptr<std::vector<T>>可以方便地在多个对象间共享数组所有权。

内容的提问来源于stack exchange,提问作者Andre Ahmed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 15:30:54