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

自定义动态数组复制时触发Segmentation fault问题排查

自定义动态数组拷贝构造函数引发段错误的解决方法

问题场景

尝试实现类似std::vector的自定义动态数组,在执行拷贝构造(Array<char> two = one;)时触发Segmentation fault (core dumped)错误,尽管已经实现了拷贝构造函数和拷贝赋值运算符,问题仍未解决。

原动态数组代码

#ifndef ARRAY_H
#define ARRAY_H

#include <cstdlib>

#define CAPACITY_SCALE_FACTOR 2

template <typename T>
struct Array
{
  T*      data;
  size_t  size;
  size_t  capacity;

  Array()
  {
    size     = 0;
    capacity = 10;
    data = (T*)malloc(capacity * sizeof(T));
  }

  ~Array()
  {
    free(data);
    data = NULL;
    size = capacity = 0;
  }

  T& operator[](size_t index);
  const T& operator[](size_t index) const;

  Array(const Array &other){
    if (array_size(other))
      for (size_t i = 0; i < other.size; i++)
        array_insert(*this, other[i]);
  }

  Array& operator=(const Array& other) {
    if (array_size(other))
      for (size_t i = 0; i < array_size(other); i++)
        array_insert(*this, other[i]);

    return *this;
  }
};


template <typename T>
T& Array<T>::operator[](size_t index)
{
  return data[index];
}

template <typename T>
const T& Array<T>::operator[](size_t index) const
{
  return data[index];
}

template <typename T>
size_t array_size(const Array<T> &array)
{
  return array.size;
}

template <typename T>
void array_insert(Array<T> &array, const T value)
{
  array[array.size] = value;

  array.size++;

  if (array.size == array.capacity)
  {
    array.capacity *= CAPACITY_SCALE_FACTOR;
    array.data = (T*)realloc(array.data, array.capacity * sizeof(T));
  }
}

template <typename T>
void array_delete(Array<T> &array, size_t index)
{
  for (size_t i = index; i < array.size - 1; i++)
  {
    array[i] = array[i + 1];
  }

  array.size--;

  if ( array.size <= ( array.capacity / (CAPACITY_SCALE_FACTOR * 2) ) )
  {
    array.capacity =
      (array.size == 0) ? 1 : array.size * CAPACITY_SCALE_FACTOR;

    array.data = (T*)realloc(array.data, array.capacity * sizeof(T));
  }
}

#endif

测试代码

#include "array.h"

int main()
{
  Array<char> one = Array<char>();
  array_insert(one, 'C');
  Array<char> two = one;

  return 0;
}

错误原因分析

自定义拷贝构造函数没有初始化新对象的data、size和capacity成员:

  • 创建two对象时,拷贝构造函数被调用,但此时two的data是未初始化的野指针,size和capacity是随机垃圾值。
  • 调用array_insert(*this, other[i])时,执行array[array.size] = value本质是访问野指针指向的内存,直接触发段错误。
  • 拷贝赋值运算符也存在同类问题:未清理当前对象原有数据,未处理自赋值情况,可能导致内存泄漏或重复释放。

修复方案

1. 正确初始化拷贝构造函数

在拷贝构造函数中,先初始化新对象的size、capacity并分配内存,再逐元素拷贝:

Array(const Array &other){
  // 初始化成员,根据源对象大小设置初始容量避免空间浪费
  size = 0;
  capacity = other.size > 0 ? other.size : 10;
  data = (T*)malloc(capacity * sizeof(T));
  
  // 逐元素拷贝源对象内容
  for (size_t i = 0; i < other.size; i++)
    array_insert(*this, other[i]);
}

2. 修复拷贝赋值运算符

拷贝赋值运算符需要先处理自赋值,清理当前对象原有资源,再完成拷贝:

Array& operator=(const Array& other) {
  // 处理自赋值,避免重复释放内存
  if (this == &other)
    return *this;
  
  // 清理当前对象的原有资源
  free(data);
  
  // 重新初始化成员
  size = 0;
  capacity = other.size > 0 ? other.size : 10;
  data = (T*)malloc(capacity * sizeof(T));
  
  // 逐元素拷贝源对象内容
  for (size_t i = 0; i < other.size; i++)
    array_insert(*this, other[i]);

  return *this;
}

额外优化建议

  • 用new/delete替代malloc/free:malloc不会调用对象构造函数,对于非POD类型会导致未初始化问题,new会自动调用构造函数。
  • 添加边界检查:在operator[]中校验index是否越界,避免非法内存访问。
  • 检查realloc返回值:realloc可能分配失败,需判断返回值,避免内存泄漏或野指针。

内容的提问来源于stack exchange,提问作者vipe4ka-visko4ka

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 07:13:14