我用std::queue
保存了一个Message
类型的智能指针(queue<shared_ptr<MessageA>
),然后在Message
类型中来将this
指针插入队列,使用std::queue::push(this)
不可以通过编译,而使用std::queue::emplace(this)
却可以,因此便使得问题在pop()
时出现:造成double free or corruption (out) 错误
#include<iostream>
#include<queue>
#include<memory>
using namespace std;
// 传递智能指针,有问题,因为std::queue::pop会析构/释放智能指针
static queue<shared_ptr<class MessageA>> QA;
// 传递裸指针,没问题,因为std::queue不会析构/释放裸指针
// static queue<class MessageA*> QA;
class MessageA {
public:
explicit MessageA(int m): msg{m} {}
void produce() {
QA.emplace(this); //! pop时会出现错误:double free or corruption (out)
cout << QA.front().use_count() << endl;
}
int msg;
};
int main() {
auto messageA = std::make_shared<MessageA>(1);
messageA->produce();
QA.pop(); // error: double free or corruption (out)
}
试着用enable_shared_from_this
和shared_from_this
来解决:失败,pop时会出现异常:bad_weak_ptr
#include<iostream>
#include<queue>
#include<memory>
using namespace std;
// 传递智能指针,有问题,因为std::queue::pop会析构/释放智能指针
static queue<shared_ptr<class MessageB>> QB;
// 传递裸指针,没问题,因为std::queue不会析构/释放裸指针
// static queue<class MessageB*> QB;
// 试图使用enable_shared_from_this来解决:失败
class MessageB: enable_shared_from_this<MessageB> {
public:
explicit MessageB(int m): msg{m} {}
void produce() {
QB.emplace(shared_from_this()); //! pop时会出现异常:bad_weak_ptr
}
int msg;
};
int main() {
auto messageB = std::make_shared<MessageB>(2);
messageB->produce();
QB.pop(); // exception: bad_weak_ptr
}
最后发现,该问题本质上相当于:
int * a = new int{};
shared_ptr<int> a1{a};
shared_ptr<int> a2{a};
// 函数结束时析构shared_ptr,也会造成double free错误
这个问题相信用智能指针的人都知道不能这么做,应该在shared_ptr
构造时new
,而不是像上面这样,会使得引用计数为1而不是为2。
而最上面的代码却通过emplace(this),使用原生指针构造了一个智能指针,而这个智能指针不与任何指针共享引用计数,最后便会产生double free错误。
由于本人才疏学浅,目前还没找到解决办法(也懒得找),但是有一个结论是肯定的:不要将原生指针(特别是this
)传递给智能指针