即使正确使用make_shared,shared_from_this()也会导致std::bad_-weak_-ptr 我正在使用独立的Asio和C++ 11创建一个C++服务器应用程序,而AM会出错,这就是我请求帮助的原因。 错误
在类即使正确使用make_shared,shared_from_this()也会导致std::bad_-weak_-ptr 我正在使用独立的Asio和C++ 11创建一个C++服务器应用程序,而AM会出错,这就是我请求帮助的原因。 错误,c++,c++11,boost-asio,shared-ptr,C++,C++11,Boost Asio,Shared Ptr,在类worker\u线程中,在从\u this()调用shared\u期间,会引发坏的\u弱的\u ptr异常,从而导致程序崩溃 布局 类connection\u manager在std::vector容器中创建并存储类型为std::shared\u ptr的对象 类worker\u线程继承自std::enable\u shared\u from\u this 类worker\u thread创建类型为std::shared\u ptr的对象 类连接需要指向类工作线程的指针(这是一个共享指针),
worker\u线程
中,在从\u this()调用shared\u期间,会引发坏的\u弱的\u ptr
异常,从而导致程序崩溃
布局
类connection\u manager
在std::vector
容器中创建并存储类型为std::shared\u ptr
的对象
类worker\u线程
继承自std::enable\u shared\u from\u this
类worker\u thread
创建类型为std::shared\u ptr
的对象
类连接
需要指向类工作线程
的指针(这是一个共享指针),以便in可以调用无效句柄_finish(std::shared_ptr)
程序流程
类worker\u线程
是通过其构造函数从类connection\u manager
使用std::make\u shared
创建的,其中有两个共享指针作为参数
connection\u管理器从worker\u线程调用void init()
在程序的后面部分,connection\u manager
调用std::shared\u ptr get\u available\u connection()
fromworker\u thread
在此方法执行期间,通过std::make_shared
创建一个新的连接
,其中一个参数是指向当前的工作线程的共享指针,该线程是通过shared_from_this()获得的
在调用shared\u from_this()
过程中,程序崩溃,出现bad\u弱\u ptr
异常
研究
根据我的研究,这种错误最常见的原因是:
当shared\u from\u在构造函数(或构造函数调用的函数)中调用this()
时
当没有指向对象的现有std::shared_ptr
时
在我的节目中:
对构造函数的调用和对get\u available\u connection()
的调用是分开的,通过终端中的输出行,似乎在调用get\u available\u connection()
时,构建并初始化了worker\u线程
connection\u管理器
类持有指向每个worker\u线程
对象的共享指针
代码
所有something\u ptr
都是std::shared\u ptr
typedef asio::executor_work_guard<asio::io_context::executor_type>
io_context_work;
std::vector<worker_thread_ptr> workers;
std::vector<io_context_ptr> io_contexts;
std::vector<io_context_work> work;
class worker_thread : std::enable_shared_from_this<worker_thread> {
public:
/// Create a worker thread.
explicit worker_thread(io_context_ptr io, config_ptr vars_global);
void init();
void join();
connection_ptr get_available_connection();
//...
explicit connection(std::shared_ptr<worker_thread> worker,
std::shared_ptr<asio::io_context> io,
config_ptr vars_parent);
connection_manager::connection_manager(config_ptr vars) {
std::size_t number_of_threads = vars->worker_threads;
while(number_of_threads > 0) {
io_context_ptr io_context(new asio::io_context);
io_contexts.push_back(io_context);
work.push_back(asio::make_work_guard(*io_context));
worker_thread_ptr worker =
std::make_shared<worker_thread>(io_context, vars);
workers.push_back(worker);
worker->init();
--number_of_threads;
}
}
connection_ptr connection_manager::get_available_connection() {
std::size_t index_of_min_thread = 0;
std::size_t worker_count = workers.size();
for(std::size_t i = 1; i < worker_count; ++i) {
if(workers[i]->active_connection_count() <
workers[index_of_min_thread]->active_connection_count())
index_of_min_thread = i;
}
return workers[index_of_min_thread]->get_available_connection();
}
worker_thread::worker_thread(io_context_ptr io,
config_ptr vars_global)
:io_context(io), active_conn_count(0), vars(vars_global),
worker(
[this]() {
if(io_context)
io_context->run();
}
) {}
void worker_thread::init() {
//Additional initialisation, this is called by connection_manager
//after this thread's construction
}
connection_ptr worker_thread::get_available_connection() {
connection_ptr conn;
if(!available_connections.empty()) {
conn = available_connections.front();
available_connections.pop();
active_connections.insert(conn);
return conn;
} else {
conn = std::make_shared<connection>(shared_from_this(), io_context, vars);
active_connections.insert(conn);
return conn;
}
}
头文件
连接管理器.hpp
typedef asio::executor_work_guard<asio::io_context::executor_type>
io_context_work;
std::vector<worker_thread_ptr> workers;
std::vector<io_context_ptr> io_contexts;
std::vector<io_context_work> work;
class worker_thread : std::enable_shared_from_this<worker_thread> {
public:
/// Create a worker thread.
explicit worker_thread(io_context_ptr io, config_ptr vars_global);
void init();
void join();
connection_ptr get_available_connection();
//...
explicit connection(std::shared_ptr<worker_thread> worker,
std::shared_ptr<asio::io_context> io,
config_ptr vars_parent);
connection_manager::connection_manager(config_ptr vars) {
std::size_t number_of_threads = vars->worker_threads;
while(number_of_threads > 0) {
io_context_ptr io_context(new asio::io_context);
io_contexts.push_back(io_context);
work.push_back(asio::make_work_guard(*io_context));
worker_thread_ptr worker =
std::make_shared<worker_thread>(io_context, vars);
workers.push_back(worker);
worker->init();
--number_of_threads;
}
}
connection_ptr connection_manager::get_available_connection() {
std::size_t index_of_min_thread = 0;
std::size_t worker_count = workers.size();
for(std::size_t i = 1; i < worker_count; ++i) {
if(workers[i]->active_connection_count() <
workers[index_of_min_thread]->active_connection_count())
index_of_min_thread = i;
}
return workers[index_of_min_thread]->get_available_connection();
}
worker_thread::worker_thread(io_context_ptr io,
config_ptr vars_global)
:io_context(io), active_conn_count(0), vars(vars_global),
worker(
[this]() {
if(io_context)
io_context->run();
}
) {}
void worker_thread::init() {
//Additional initialisation, this is called by connection_manager
//after this thread's construction
}
connection_ptr worker_thread::get_available_connection() {
connection_ptr conn;
if(!available_connections.empty()) {
conn = available_connections.front();
available_connections.pop();
active_connections.insert(conn);
return conn;
} else {
conn = std::make_shared<connection>(shared_from_this(), io_context, vars);
active_connections.insert(conn);
return conn;
}
}
连接.hpp
typedef asio::executor_work_guard<asio::io_context::executor_type>
io_context_work;
std::vector<worker_thread_ptr> workers;
std::vector<io_context_ptr> io_contexts;
std::vector<io_context_work> work;
class worker_thread : std::enable_shared_from_this<worker_thread> {
public:
/// Create a worker thread.
explicit worker_thread(io_context_ptr io, config_ptr vars_global);
void init();
void join();
connection_ptr get_available_connection();
//...
explicit connection(std::shared_ptr<worker_thread> worker,
std::shared_ptr<asio::io_context> io,
config_ptr vars_parent);
connection_manager::connection_manager(config_ptr vars) {
std::size_t number_of_threads = vars->worker_threads;
while(number_of_threads > 0) {
io_context_ptr io_context(new asio::io_context);
io_contexts.push_back(io_context);
work.push_back(asio::make_work_guard(*io_context));
worker_thread_ptr worker =
std::make_shared<worker_thread>(io_context, vars);
workers.push_back(worker);
worker->init();
--number_of_threads;
}
}
connection_ptr connection_manager::get_available_connection() {
std::size_t index_of_min_thread = 0;
std::size_t worker_count = workers.size();
for(std::size_t i = 1; i < worker_count; ++i) {
if(workers[i]->active_connection_count() <
workers[index_of_min_thread]->active_connection_count())
index_of_min_thread = i;
}
return workers[index_of_min_thread]->get_available_connection();
}
worker_thread::worker_thread(io_context_ptr io,
config_ptr vars_global)
:io_context(io), active_conn_count(0), vars(vars_global),
worker(
[this]() {
if(io_context)
io_context->run();
}
) {}
void worker_thread::init() {
//Additional initialisation, this is called by connection_manager
//after this thread's construction
}
connection_ptr worker_thread::get_available_connection() {
connection_ptr conn;
if(!available_connections.empty()) {
conn = available_connections.front();
available_connections.pop();
active_connections.insert(conn);
return conn;
} else {
conn = std::make_shared<connection>(shared_from_this(), io_context, vars);
active_connections.insert(conn);
return conn;
}
}
worker\u thread.cpp
typedef asio::executor_work_guard<asio::io_context::executor_type>
io_context_work;
std::vector<worker_thread_ptr> workers;
std::vector<io_context_ptr> io_contexts;
std::vector<io_context_work> work;
class worker_thread : std::enable_shared_from_this<worker_thread> {
public:
/// Create a worker thread.
explicit worker_thread(io_context_ptr io, config_ptr vars_global);
void init();
void join();
connection_ptr get_available_connection();
//...
explicit connection(std::shared_ptr<worker_thread> worker,
std::shared_ptr<asio::io_context> io,
config_ptr vars_parent);
connection_manager::connection_manager(config_ptr vars) {
std::size_t number_of_threads = vars->worker_threads;
while(number_of_threads > 0) {
io_context_ptr io_context(new asio::io_context);
io_contexts.push_back(io_context);
work.push_back(asio::make_work_guard(*io_context));
worker_thread_ptr worker =
std::make_shared<worker_thread>(io_context, vars);
workers.push_back(worker);
worker->init();
--number_of_threads;
}
}
connection_ptr connection_manager::get_available_connection() {
std::size_t index_of_min_thread = 0;
std::size_t worker_count = workers.size();
for(std::size_t i = 1; i < worker_count; ++i) {
if(workers[i]->active_connection_count() <
workers[index_of_min_thread]->active_connection_count())
index_of_min_thread = i;
}
return workers[index_of_min_thread]->get_available_connection();
}
worker_thread::worker_thread(io_context_ptr io,
config_ptr vars_global)
:io_context(io), active_conn_count(0), vars(vars_global),
worker(
[this]() {
if(io_context)
io_context->run();
}
) {}
void worker_thread::init() {
//Additional initialisation, this is called by connection_manager
//after this thread's construction
}
connection_ptr worker_thread::get_available_connection() {
connection_ptr conn;
if(!available_connections.empty()) {
conn = available_connections.front();
available_connections.pop();
active_connections.insert(conn);
return conn;
} else {
conn = std::make_shared<connection>(shared_from_this(), io_context, vars);
active_connections.insert(conn);
return conn;
}
}
worker\u线程::worker\u线程(io\U上下文\U ptr io,
配置变量(全局)
:io上下文(io)、活动连接计数(0)、变量(变量全局),
工人(
[这](){
如果(io_上下文)
io_上下文->运行();
}
) {}
无效工作线程::init(){
//附加初始化,由连接管理器调用
//在这个线程的构造之后
}
连接\u ptr工作线程::获取可用的\u连接(){
连接接头;
如果(!available_connections.empty()){
conn=可用的_连接。前();
可用的_连接。pop();
活动_连接。插入(连接);
返回连接;
}否则{
conn=std::make_shared(来自_this()、io_上下文、vars的共享_);
活动_连接。插入(连接);
返回连接;
}
}
如果这个问题以前被回答过,我很抱歉,但我试图解决这个问题,在尝试了一段时间后,我决定最好寻求帮助
编辑
这是一个最低限度的测试,它失败了。它需要CMake,并且您可能必须更改所需的最低版本
我认为您的问题可能是使用默认的私有继承
下面是一个程序崩溃的简单示例:
class GoodUsage : public std::enable_shared_from_this<GoodUsage>
{
public:
void DoSomething()
{
auto good = shared_from_this();
}
};
class BadUsage : std::enable_shared_from_this<BadUsage> // private inheritance
{
public:
void DoSomething()
{
auto bad = shared_from_this();
}
};
int main()
{
auto good = std::make_shared<GoodUsage>();
auto bad = std::make_shared<BadUsage>();
good->DoSomething(); // ok
bad->DoSomething(); // throws std::bad_weak_ptr
}
class-GoodUsage:public-std::从\u中启用\u共享\u
{
公众:
无效剂量测定法()
{
auto good=从_this()共享_;
}
};
类BadUsage:std::从\u这个//私有继承中启用\u共享\u
{
公众:
无效剂量测定法()
{
auto bad=从_this()共享_;
}
};
int main()
{
自动良好=标准::使_共享();
auto bad=std::make_shared();
好->DoSomething();//好的
bad->DoSomething();//抛出std::bad_弱_ptr
}
请花点时间阅读。我没有看到任何常见错误。您是否检查过没有因为多线程访问而中断任何内容?(必要时使用锁),有时这种错误会导致某些内存损坏,或者是某些“未定义行为”的后续operation@PetarNikićclass
es默认为私有继承。看到了,很高兴是这样。看来我在答案上被打败了@NinaKaprez的回答涵盖了这一点。重新编写了标题,使其成为针对这一反复出现的陷阱的优秀搜索。(我以前见过,但我花了太长时间才再次意识到这一点)。这东西是用来做的