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

动态对象指针数组插入新元素时内存分配错误排查求助

问题分析与修复方案

咱们直接切入问题核心,一步步排查并修复你的Array类内存错误问题:

1. 最致命的问题:缺失默认构造函数

你的BinaryHeap构造函数里调用了new Array(),也就是默认构造函数,但你的Array类并没有显式定义这个构造——编译器自动生成的默认构造不会初始化_headPtr和arraySize这两个成员变量。这直接导致:

  • arraySize变成随机的垃圾值,第一次调用pushBack时,if (arraySize == 0)的条件几乎不可能成立,直接进入else分支
  • 用垃圾值的arraySize +1去分配内存,要么分配超大数组导致内存不足,要么因为负数触发内存分配失败,直接崩溃在new Edge*[arraySize +1]这一行

2. 次要问题:pushBack的逻辑冗余+误删外部对象

你原来的pushBack里写了delete _headPtr[i],这是错误的——这些Edge*是外部代码(比如BinaryHeap里的new Edge(...))创建的,Array只是存储指针的容器,不应该负责销毁这些Edge对象,否则外部再访问这些对象就会触发_free_dbg这类内存错误,你注释掉这部分是正确的。

另外,pushBack的if-else逻辑可以简化,不用分情况处理初始状态。


修复后的完整代码实现

第一步:补充Array类的默认构造与必要方法

#include "Edge.h"

class Array {
private:
    Edge** _headPtr;
    int arraySize;
public:
    // 默认构造:初始化空数组
    Array();
    // 带初始容量的构造
    Array(int initialSize);
    // 析构函数:释放指针数组(注意不释放Edge对象)
    ~Array();
    // 禁用拷贝构造与赋值(避免浅拷贝导致的重复释放)
    Array(const Array&) = delete;
    Array& operator=(const Array&) = delete;

    void pushBack(Edge* element);
    // 你需要的getSize方法
    int getSize() const { return arraySize; }
    // 其他函数...
};

第二步:实现构造与析构函数

// 默认构造:初始化空状态
Array::Array() : _headPtr(nullptr), arraySize(0) {}

// 带初始容量的构造
Array::Array(int initialSize) : arraySize(0), _headPtr(nullptr) {
    if (initialSize > 0) {
        arraySize = initialSize;
        _headPtr = new Edge*[initialSize];
        // 初始化数组内的指针为nullptr,避免野指针
        for (int i = 0; i < initialSize; ++i) {
            _headPtr[i] = nullptr;
        }
    }
    // 如果initialSize<=0,保持空状态
}

// 析构函数:只释放指针数组本身,不释放Edge对象
Array::~Array() {
    delete[] _headPtr;
    _headPtr = nullptr;
    arraySize = 0;
}

第三步:简化并修复pushBack方法

void Array::pushBack(Edge* element) {
    // 分配新的指针数组,容量+1
    Edge** tempPtr = new Edge*[arraySize + 1];
    
    // 如果原数组有元素,拷贝过去
    if (arraySize > 0) {
        memcpy(tempPtr, _headPtr, arraySize * sizeof(Edge*));
        // 释放原指针数组
        delete[] _headPtr;
    }
    
    // 添加新元素
    tempPtr[arraySize] = element;
    // 更新成员变量
    _headPtr = tempPtr;
    arraySize++;
}

修复逻辑说明

  • 默认构造显式初始化_headPtr为nullptr、arraySize为0,彻底避免了未初始化的垃圾值问题
  • 简化后的pushBack逻辑统一处理空数组和非空数组的情况,减少分支出错概率
  • 析构函数只释放指针数组本身,不会误删外部创建的Edge对象,避免了_free_dbg错误
  • 禁用拷贝构造与赋值,防止浅拷贝导致的重复释放内存问题(如果需要深拷贝,可以自行修改拷贝逻辑)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:04:24