Std::shared_ptr уничтожает, даже если ссылка на него существуетC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Std::shared_ptr уничтожает, даже если ссылка на него существует

Сообщение Anonymous »

Я использую сопрограммы boost::asio и c++20 в своей собственной библиотеке сокетов/сети. У меня есть класс сервера, который создает общий_ptr для класса сеанса при принятии и удерживает сеанс в наборе. Сокет постоянно асинхронно читается так:

Код: Выделить всё

void Socket::read(const String &delim) {
boost::asio::async_read_until(_sock, boost::asio::dynamic_buffer(_recBuf), delim,
boost::asio::bind_executor(_readStrand,
[this, delim = delim, self = shared_from_this()] (const boost::system::error_code& ec, const std::size_t bytes) {
// LOGIC FOR HANDLING THE READ ...
Socket::handleMsg();
Socket::read(delim);
}));
}

void Socket::doWrite(std::shared_ptr str) {
asio::async_write(_sock, asio::buffer(*str),
asio::bind_executor(_writeStrand,
[this, str, self = shared_from_this()] (const boost::system::error_code& ec, const std::size_t bytes) {
// LOGIC TO HANDLE WRITE
// WILL EITHER POP NEXT MESSAGE OFF QUEUE OR EXIT
}));
}
Здесь происходит обработка сообщений:

Код: Выделить всё

bool Socket::handleMsg(const object::String &msg) {
try {
auto self = shared_from_this();
co_spawn(_asyncHandleMsgStrand, [this, self, m] () -> boost::asio::awaitable {
try {
co_await handleMsgInt(m);
}
catch (const std::exception &e) {
lh.e(fmt::format("{:s}", e.what()));
stop_int();
}
},
[this, self] (std::exception_ptr e) {
if (e) {
_ioc.post([e, self] {
std::rethrow_exception(e);
});
}
});
}
catch (const std::exception &e) {
lh.e(fmt::format("{:s}", e.what()));
stop_int();
return false;
}

return true;
}
Проблема в том, что после обработки сообщения, которое приводит к приостановке co_await в handleMsgInt(), при уничтожении лямбды сопрограммы в handleMsg() само shared_ptr разрушает. В деструкторе я проверяю, существует ли еще ссылка на сервер, и она существует, но метод use_count() возвращает 0.
Что-то еще, с чем я столкнулся, чего может просто не хватать знаний с моей стороны заключается в том, что после создания сеанса здесь:

Код: Выделить всё

inline static std::shared_ptr create(boost::asio::io_context &ioc, boost::asio::ip::tcp::socket &sock, Server &server) {
return std::shared_ptr(new Socket(ioc, sock, server));
}
Я записываю адрес this (внутри конструктора Socket), полученный адресshared_ptr.get() иshared_from_this().get() адрес. Эти три адреса разные. Socket наследуется от базового класса, который, в свою очередь, наследуется от Enable_shared_from_this. Не знаю, влияет ли это на что-нибудь.

Код: Выделить всё

(2024/05/31 18:19:02.775665476)  (trace)   Socket: this: 0x7fffe8001000
(2024/05/31 18:19:02.775706976)  (trace)   Server: shared_ptr before adding to sessions set: 0x7fffe8001150, ref: 1
(2024/05/31 18:19:02.775727176)  (trace)   Server: shared_ptr after adding to sessions: 0x7fffe8001150, ref: 2
(2024/05/31 18:19:02.775739376)  (trace)   Server: sessions.begin()->get(): 0x7fffe8001150, ref: 2
(2024/05/31 18:19:02.775747376)  (trace)   Server: shared from this: 0x7fffe8001218, ref: 3
Я понимаю, что это не так уж много информации, на которую можно опереться, думаю, я ищу очевидные ошибки или вещи, о которых следует помнить.
Забыл указать, что класс сокета имеет виртуальное ромбовидное наследование базового класса, который наследуется от Enable_shared_from_this. Я не знаю, изменит ли это поведение.

Подробнее здесь: https://stackoverflow.com/questions/785 ... -it-exists
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»