实现自定义类vector泛型数据类型时添加string元素触发Segmentation fault
问题触发原因
- 浅拷贝破坏非平凡类型内部结构:
std::memcpy是逐字节的浅拷贝操作,仅适用于内存布局连续、无内部堆资源管理的平凡类型(如char*、基础数值类型)。对于std::string、自定义结构体这类持有内部堆指针的非平凡类型,直接memcpy会复制原始对象的指针值,当原数组被delete[]释放时,对象内部的堆资源也会被回收,新数组里的拷贝对象就持有了野指针,后续访问/赋值时就会触发段错误。 - 拷贝长度越界:
resize方法里先更新了length_为扩容后的长度,再用新的length_作为拷贝长度读取旧数组内容,但旧数组仅持有扩容前长度的有效元素,多读取的部分属于非法内存访问,也是段错误的直接诱因之一。 - 额外的默认构造开销与兼容性问题:
new type[length_]会默认构造N个目标类型对象,对于无默认构造函数的自定义类型会直接编译失败,后续赋值操作也属于不必要的性能损耗。
修复方案
- 修正resize的执行顺序,先拷贝旧长度的有效元素,再更新长度;
- 替换
memcpy为对象级的拷贝/移动操作,兼容非平凡类型; - 补充必要的析构、迭代器逻辑,完善类的基础功能。
修复后核心代码示例
#include <utility> // 用于std::移动语义支持 template<typename type> class table { private: type* elements = nullptr; // 初始空数组无需new[0]分配无效内存 unsigned int length_ = 0; void resize(int change) { unsigned int old_len = length_; unsigned int new_len = old_len + change; if (new_len == 0) { delete[] elements; elements = nullptr; length_ = 0; return; } // 先分配新数组内存 type* new_elements = new type[new_len]; // 逐个移动旧元素,仅处理旧长度的有效内容 for (unsigned int i = 0; i < old_len; ++i) { new_elements[i] = std::move(elements[i]); } // 释放旧数组资源 delete[] elements; // 更新成员变量 elements = new_elements; length_ = new_len; } public: // 析构函数避免内存泄漏 ~table() { delete[] elements; } // 支持左值、右值元素添加 void append(const type& element) { resize(1); elements[length_ - 1] = element; } void append(type&& element) { resize(1); elements[length_ - 1] = std::move(element); } // 实现迭代器接口支持范围for循环 type* begin() { return elements; } type* end() { return elements + length_; } const type* begin() const { return elements; } const type* end() const { return elements + length_; } };
内容的提问来源于stack exchange,提问作者Kazafka
相关产品推荐
相关产品推荐

