can't delete an incomplete type unique_ptr C++

311
29 марта 2017, 18:08

Здравствуйте. После уничтожения класса TCPSession выбрасывается исключение. Вот фрагмент кода. memory

template<class _Ty2,
        class = typename enable_if<is_convertible<_Ty2 *, _Ty *>::value,
            void>::type>
        default_delete(const default_delete<_Ty2>&) _NOEXCEPT
        {   // construct from another default_delete
        }
    void operator()(_Ty *_Ptr) const _NOEXCEPT
        {   // delete a pointer
        static_assert(0 < sizeof (_Ty),
            "can't delete an incomplete type");
        delete _Ptr; // can't delete an incomplete type unique_ptr
        }
    };

Вот мой код.

main.cpp

#include "TCPserver.h"
using namespace std;
int main()
{
    try
    {
        TCPServer<TCPSession> server;
        server.start_server();
    }
    catch (const std::exception e)
    {
        cerr << "Error: " << e.what() << endl;
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

TCPServer.h

#include "TCPSession.h"
template <class ConnectHundler>
class TCPServer 
{
    using shared_handler_t = std::shared_ptr<ConnectHundler>;
public:
    TCPServer(int thread_count = 1)
        : thread_count_(thread_count)
        , acceptor_(io_service_)
    {}
    void start_server(uShort port = 1973);
    void handle_new_connection(shared_handler_t hadler
        , system::error_code const & error);
private:
    int thread_count_;
    std::vector<std::thread> thread_pool_;
    asio::io_service io_service_;
    asio::ip::tcp::acceptor acceptor_;
};

template <class ConnectHundler>
inline void TCPServer<ConnectHundler>::start_server(uShort port)
{
    auto handler = std::make_shared<ConnectHundler>(io_service_); // 
    // set up acceptor to listen on the tcp port
    asio::ip::tcp::endpoint endpoint(asio::ip::tcp::v4(), port);
    acceptor_.open(endpoint.protocol());
    acceptor_.set_option(asio::ip::tcp::acceptor::reuse_address(true));
    acceptor_.bind(endpoint);
    acceptor_.listen();
    acceptor_.async_accept(handler->socket(), [=](auto ec)
    {
        handle_new_connection(handler, ec);
    });
    for (size_t i = 0; i < thread_count_; ++i)
    {
        thread_pool_.emplace_back([=] { io_service_.run(); });
    }
}
template <class ConnectHundler>
inline void TCPServer<ConnectHundler>::handle_new_connection(shared_handler_t hadler, system::error_code const & error)
{
    if (error)
    {
        return;
    }
    hadler->start(); //
    auto new_handler = std::make_shared<ConnectHundler>(io_service_);
    acceptor_.async_accept(new_handler->socket(), [=](auto ec)
    {
        handle_new_connection(new_handler, ec);
    });
}

TCPSession.h

#pragma once
#include "Packet.h"
#include "AccountServer.h"
class TCPSession : public std::enable_shared_from_this<TCPSession>
{
public:
    ~TCPSession();
    TCPSession(boost::asio::io_service & service);
    std::unique_ptr<char>& receive_buffer()
    {
        return eceive_buffer_;
    }
    ...
private:
    asio::io_service & service_;
    asio::ip::tcp::socket socket_;
    std::unique_ptr<char> receive_buffer_;
    ...
};

TCPSession.cpp

TCPSession::~TCPSession()
{
}
TCPSession::TCPSession(boost::asio::io_service & service)
    : service_(service)
    , socket_(service)
    , receive_buffer_(new char[64 * 1024]())
{}
void TCPSession::start()
{
    ...
    read_packet_len();
}
void TCPSession::read_packet_len()
{
    receive_buffer_.reset(new char[2]());
    async_read(socket_, asio::buffer(receive_buffer_.get(), 2)
        , [my = shared_from_this()](
            boost::system::error_code const & error, size_t bytes_xfer){
                my->read_packet();
    });
}
void TCPSession::read_packet()
{
    uShort l_pktlen = 0;
    memcpy((char*)&l_pktlen, receive_buffer_.get(), sizeof(uShort));
    boost::endian::endian_reverse_inplace<uShort>(l_pktlen);
    ...
        async_read(socket_, asio::buffer(receive_buffer_.get() + 2, l_pktlen - 2)
            , [my=shared_from_this(), l_pktlen](boost::system::error_code const & error, size_t bytes_xfer)
        {
            RPacket l_rpkt;
            memcpy(const_cast<char*>(l_rpkt.getPktAddr()), my->receive_buffer().get(), l_pktlen);
            ...         
        });
}
Answer 1

В TCPSession.h у вас присутствует следующее объявление переменной:

std::unique_ptr<char> receive_buffer_;

которая инициализируется так:

receive_buffer_(new char[64 * 1024]())

receive_buffer_ - это умный указатель на char, а не на массив char, из-за чего вызывается delete а не delete[]. Используйте

std::unique_ptr<char[]> receive_buffer_;

P.S. На всякий случай замечу, что с std::shared_ptr это не сработает. А вообще, лучше использовать std::vector для массивов.

READ ALSO
Как открыть исходный код картинки в C++

Как открыть исходный код картинки в C++

Здравствуйте! Помогите пожалуйста с интересным вопросом) Я хотел бы открыть через C++ файл и просмотреть его содержимое, но это не простой...

298
куча mmap в простейшем коде дампа stacktrace

куча mmap в простейшем коде дампа stacktrace

здравствуйте, вот решил прогнать через strace бинарник хелловорлда:

213