gpt4 book ai didi

c++ - 即使正确使用 make_shared,shared_from_this() 也会导致 std::bad_weak_ptr

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:53:10 33 4
gpt4 key购买 nike

我正在使用独立的 Asio 和 C++11 创建一个 C++ 服务器应用程序,但遇到错误,这就是我寻求帮助的原因。

错误

在类里面worker_thread , 在通话期间 shared_from_this() , 一个 bad_weak_ptr引发异常,导致程序崩溃。

布局

  1. 类(class) connection_manager创建并存储 std::shared_ptr<worker_thread> 类型的对象在 std::vector 里面容器
  2. 类(class) worker_thread继承自 std::enable_shared_from_this<worker_thread> .
  3. 类(class) worker_thread创建 std::shared_ptr<connection> 类型的对象.
  4. 类(class) connection需要一个指向类 worker_thread 的指针(这是一个共享指针) , 这样就可以调用 void handle_finish(std::shared_ptr<connection>)

程序流程

  1. 类(class) worker_thread是通过其构造函数从类 connection_manager 创建的使用 std::make_shared<worker_thread>以两个共享指针作为参数。
  2. void init()worker_thread 调用通过 connection_manager
  3. 稍后在程序中,connection_manager电话 std::shared_ptr<connection> get_available_connection()来自 worker_thread
  4. 在此方法执行期间,一个新的 connection通过 std::make_shared<connection> 创建,其中一个参数是指向 current worker_thread 的共享指针通过shared_from_this()获得
  5. shared_from_this() 期间调用,程序崩溃并显示 bad_weak_ptr异常(exception)。

研究

根据我的研究,导致此错误的最常见原因是:

  1. 何时shared_from_this()在构造函数(或由构造函数调用的函数)中调用
  2. 当不存在 std::shared_ptr 时指向对象。

在我的程序中:

  1. 调用构造函数和 get_available_connection()是分开的,并且通过终端中的输出行,似乎 worker_thread在调用 get_available_connection() 时构造和初始化发生
  2. connection_manager类拥有指向每个 worker_thread 的共享指针对象。

代码

全部something_ptrstd::shared_ptr<something>

头文件

connection_manager.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;

worker_thread.hpp

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();
//...

connection.hpp

explicit connection(std::shared_ptr<worker_thread> worker,
std::shared_ptr<asio::io_context> io,
config_ptr vars_parent);

源文件

connection_manager.cpp

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.cpp

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;
}
}

如果这个问题之前已经回答过,我很抱歉,但我试图解决这个问题,在尝试了一段时间之后,我决定寻求帮助会更好。

编辑这是一个最低限度的测试,它失败了。它需要 CMake,您可能需要更改所需的最低版本

Google Drive link

最佳答案

我认为您的问题可能是您使用了默认的 private 继承。

这是一个程序崩溃的简单示例:

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
}

关于c++ - 即使正确使用 make_shared,shared_from_this() 也会导致 std::bad_weak_ptr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50318414/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com