在std::vector中使用自定义struct A的构造函数与崩溃问题排查
问题分析与解决方案
首先要明确:你的struct A定义本身完全没有问题——不管是让编译器自动生成默认的拷贝/移动构造函数、赋值运算符,还是显式定义(或者用=default),都是正确的。因为A的成员是std::string,它本身已经正确实现了拷贝、移动、析构等语义,编译器生成的默认函数会自动调用成员的对应操作,完全能满足std::vector的要求。
那问题出在哪里?看你的错误栈里的这一行:
[Switching to Thread 0x7fffe97fa700 (LWP 88073)]
这说明你的程序是多线程运行的,而std::vector的所有成员函数都不是线程安全的!当多个线程同时对同一个B对象的A_v进行操作(比如一个线程在调用resize扩容,另一个线程在通过operator[]赋值),就会引发数据竞争,导致内存损坏,从而出现你看到的段错误或者double free错误。
解决方案:添加线程同步机制
你需要给所有操作A_v的函数添加互斥锁,确保同一时间只有一个线程能访问和修改vector。比如用std::mutex和std::lock_guard:
#include <mutex> class B { private: std::vector<A> A_v; std::mutex mtx; // 新增互斥锁,保护A_v的访问 public: void preAllocate(){ std::lock_guard<std::mutex> lock(mtx); // 自动加锁,作用域结束自动解锁 A_v.resize(1000); } void addA(int id, A& a){ std::lock_guard<std::mutex> lock(mtx); assert(id < A_v.size()); A_v[id].key = a.key; A_v[id].key2 = a.key2; if (A_v.size() - id < 100) A_v.resize(A_v.size() + 100); } };
额外注意事项
- 确保所有直接或间接访问
A_v的代码都在锁的保护下——如果你的程序里还有其他函数操作A_v,也要加上同样的锁逻辑。 - 你完全可以删除
A中手动定义的拷贝/移动构造函数和赋值运算符,编译器生成的默认版本已经足够用,代码更简洁也不容易出错。
内容的提问来源于stack exchange,提问作者Xing Lin
相关产品推荐
相关产品推荐

