cpp удаляет старый указатель и повторно инициализирует его

0

У меня есть tcp-сервер, который требует, чтобы ровно один клиент мог подключиться к нему в любое время. в любое время, когда подключается новый клиент, старый сеанс должен быть удален и создан новый сеанс.

прямо сейчас, я делаю это так:

void TcpServer::start_accept() {
    Logger::info("[TCPSERVER] TCP Server starting to accept", __LINE__, __FILE__);

    if (session) { // check if there is any older session, if so..delete them
        session = NULL;
        delete session;
    }

    session = new TcpServerSession(io_service_);
    acceptor_.async_accept(session->socket(), boost::bind(&TcpServer::handle_accept, this, session, boost::asio::placeholders::error));
}

поэтому в любое время, когда я хотел бы отправить сообщение клиенту, это делается следующим образом:

int TcpServer::sendMsgToClient(std::string msg) {

    if (session)
        session->sendMsgToClient(msg);
}

Мне интересно, правильно ли это сделано? в основном основной момент - удаление указателя и повторное создание it.whats лучший способ сделать это?

Теги:
pointers
boost

5 ответов

4
Лучший ответ
if (session) { // check if there is any older session, if so..delete them
    session = NULL;
    delete session;
}

Это совершенно неправильно! Вы закрываете session, протекаете все, что в нем есть, а затем delete NULL, который абсолютно ничего не делает.

Чтобы быть безопасным для исключений, вы не должны delete старый сеанс, пока не будете успешно созданы новые. Что-то вроде этого:

if (session) {
    // Create and initialise the new session first
    TcpServerSession* newSession = new TcpServerSession(io_service_);

    // Don't know what this line does, but I assume it important
    acceptor_.async_accept(newSession->socket(), boost::bind(&TcpServer::handle_accept, this, newSession, boost::asio::placeholders::error));

    std::swap(session, newSession); // Put the new one in place
    delete newSession; // delete the old one.
}

Собственно, это предполагает, что async_accept не выбрасывает. Если это возможно, вам нужно быть осторожным, чтобы удалить newSession, возможно, с каким-то умным указателем.

5

Просто используйте std::unique_ptr<>:

session.reset(new TcpServerSession(io_service_));

Он получает все правильно: не удаляйте старый объект до того, как новый будет доступен, никогда не будет иметь точку сеанса для чего-то недействительного, и даже при наличии исключений утечка памяти не будет.

  • 1
    +1 полностью так, как я бы это сделал.
2
    session = NULL;
    delete session;

Скорее всего, это не так. Если вы замените значение, которое удерживает session (который указывает на блок памяти, выделенный new), перед вызовом delete на нем, вы фактически теряете этот блок памяти, вызывая утечку памяти. Единственная причина, по которой этот код не взорван, заключается в том, что вызов delete с помощью NULL гарантированно является no-op.

Таким образом, вы должны заменить код следующим:

    delete session;
    session = NULL; // or nullptr if you've got C++11

Это гарантирует, что память будет правильно освобождена.

  • 0
    Как предположил Бармар, присвоение NULL в этом случае не имеет смысла, так как значение мгновенно перезаписывается без чтения. Виноват.
  • 0
    Не так плохо, как вы думаете. Если new или конструктор выдает исключение, новое значение указателя никогда не попадет в session . Без очистки старого вы попадете в этот или другой код очистки, который попытается снова удалить то же значение. И NULL / nullptr не является решением, persese; умный указатель есть.
Показать ещё 1 комментарий
0
if (session) { // check if there is any older session, if so..delete them
    session = NULL;
    delete session;
}

Этот код говорит:

Если сеанс указывает на некоторый действительный объект (вместо того, чтобы быть нулевым), то прекратите указывать на него (вместо этого укажите NULL), а затем удалите то, что сейчас указывает на сеанс, то есть ничего не удаляйте.

Это очень плохо. Это настоящая утечка памяти.

Комментарий - ложь.

0

Избавьтесь от session = NULL перед delete session. Вы пытаетесь удалить нулевой указатель.

Вам не нужно устанавливать его в null, потому что вы сразу же настроите его на новый сеанс TCP.

  • 2
    На самом деле, вы должны, потому что new может бросить и покинуть сессию в несогласованном состоянии. Но у BoBTFish есть лучшее решение; не удаляйте старую перед созданием новой сессии.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню