自定义动态数组复制时触发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
相关产品推荐
相关产品推荐

