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

C++ BitArray2类析构报错:free()无效指针问题求助

问题:BitArray2类析构函数触发free(): invalid pointer错误

背景

从Java转C++,为理解底层原理实现了支持双[]访问的BitArray2类,功能运行正常,但析构函数调用时出现以下错误:

free(): invalid pointer
Aborted (core dumped)

推测问题源于重复释放指针,附上类实现、示例代码及问题分析。

类实现示例(问题代码)

#include <cstdlib>

class BitArray2 {
private:
    unsigned char* data;
    int size;

public:
    BitArray2(int n) : size(n) {
        // 按字节分配内存存储位数据
        data = (unsigned char*)malloc((size + 7) / 8);
    }

    // 编译器生成的默认拷贝构造函数(浅拷贝)
    // BitArray2(const BitArray2& other) = default;

    ~BitArray2() {
        free(data);
    }

    // const版本[]访问
    bool operator[](int index) const {
        int byteIdx = index / 8;
        int bitIdx = index % 8;
        return (data[byteIdx] >> bitIdx) & 1;
    }

    // 非const版本[]访问
    bool& operator[](int index) {
        int byteIdx = index / 8;
        int bitIdx = index % 8;
        // 这里仅为示例实现,实际可能有其他逻辑
        static bool temp_bit;
        temp_bit = (data[byteIdx] >> bitIdx) & 1;
        return temp_bit;
    }
};

示例应用代码

int main() {
    BitArray2 arr(16);
    BitArray2 arr_copy = arr; // 触发浅拷贝
    return 0;
}

问题原因

核心问题是浅拷贝导致的重复内存释放:

  • 当你没有显式定义拷贝构造函数时,编译器会生成默认的浅拷贝版本,直接复制data指针的值,而非重新分配内存复制数据。
  • 示例中arr和arr_copy共享同一块堆内存,main函数结束时,两个对象依次析构:第一个对象调用free(data)释放内存,第二个对象析构时再次调用free(data),此时指针已指向被释放的内存,触发invalid pointer错误。
  • 其他可能诱因:混用malloc/free和new/delete(比如用delete释放malloc分配的内存)、数组越界篡改了data指针的值,但结合你的推测,浅拷贝是最可能的原因。

解决方法

1. 实现深拷贝

显式定义拷贝构造函数和赋值运算符,为新对象重新分配内存并复制数据:

// 拷贝构造函数
BitArray2(const BitArray2& other) : size(other.size) {
    data = (unsigned char*)malloc((size + 7) / 8);
    if (data != nullptr) {
        // 逐字节复制数据
        for (int i = 0; i < (size + 7) / 8; ++i) {
            data[i] = other.data[i];
        }
    }
}

// 赋值运算符(遵循拷贝交换惯用法,避免自我赋值问题)
BitArray2& operator=(BitArray2 other) {
    std::swap(data, other.data);
    std::swap(size, other.size);
    return *this;
}

2. 禁用拷贝操作

如果你的类不需要被拷贝,可以显式禁用拷贝构造和赋值运算符:

BitArray2(const BitArray2&) = delete;
BitArray2& operator=(const BitArray2&) = delete;

3. 检查内存分配释放匹配

确保所有用malloc分配的内存都用free释放,用new分配的用delete释放,不要混用两种内存管理方式。

相关学习资料

  • 《C++ Primer》:重点学习“类的拷贝控制”章节,掌握拷贝构造函数、赋值运算符、析构函数的三/五法则,理解编译器默认生成函数的行为。
  • 《Effective C++》:条款11(处理operator=中的自我赋值)、条款13(用对象管理资源),深入理解C++资源管理的核心原则。
  • 《More Effective C++》:条款27(要求或禁止对象拷贝),学习如何控制类的拷贝行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 00:45:57