memcpy, который не имеет смысла для меня - PullRequest
1 голос
/ 03 мая 2011

У меня есть некоторый код подключения к сокету, который использует boost :: asio, который считывает из сокета первые 5 символов, из которых он может определить, была ли сжатая отправленная строка с использованием библиотеки zlib.Проект, который я сейчас делаю, представляет собой переписывание чего-то существующего, поэтому я взял часть существующего кода и сделал его более похожим на C ++ вместо C. Однако в коде он вызывает memcpy, что мне кажетсяполностью избыточный, однако, если этого вызова нет, вызов async_read никогда не вызывается, чего я не получаю.Зачем?Какова цель этого memcpy вызова и почему он должен быть там, по всем показателям?

/*check for zlib compression and then call handle_read_s which gets the rest of the data and decompresses if necessary.*/
/// buff is a vector<char>
/// tempbuff is a char[5]
void tcp_connection::handle_read(const boost::system::error_code& err, size_t bytes_transferred, endpoint_ptr ptr)
{
    unsigned long maxsz = 1024; //0xffffffff;
    size_t size = 1024;
    b_zlib = false;

    if (!err || err ==  boost::asio::error::message_size)
    {
        if (bytes_transferred >= 4)
        {
            if (tempbuff[0] == 'Z')
                b_zlib = true;

            //Remove 4 bytes & remove memcpy
            memcpy(&maxsz, &tempbuff[1], 4);   //removing this makes my code unworkable, I don't get it?
            buff.resize(maxsz);  //passing anything else here also kills it?!!
            boost::asio::async_read(socket_, boost::asio::buffer(buff), boost::bind(&tcp_connection::handle_read_s, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, ptr));
        }
    }   

}

Ответы [ 4 ]

4 голосов
/ 03 мая 2011

Этот код сообщает вам размер требуемого буфера.

memcpy(&maxsz, &tempbuff[1], 4);

И этот код изменяет размер вашего буфера

buff.resize(maxsz);
2 голосов
/ 03 мая 2011

Цель memcpy - сделать код непереносимым и внести неловкие ошибки при компиляции кода на другом компьютере.Для этого в maxsz устанавливается какое-то значение в зависимости от того, что вы только что прочитали.Правильное значение зависит от машины.(Если я могу доверять именам, существует также неопределенное поведение: bytes_transferred равно 4. И будет неопределенное поведение, если вы портируете на компьютер, где unsigned long равен 64 битам.)

В зависимостив протоколе вы должны использовать:

maxsz = static_cast<unsigned char>(tempbuff[1])
    | (static_cast<unsigned char>(tempbuff[2]) << 8)
    | (static_cast<unsigned char>(tempbuff[3]) << 16)
    | (static_cast<unsigned char>(tempbuff[4]) << 24);

или

maxsz = (static_cast<unsigned char>(tempbuff[1]) << 24)
    | (static_cast<unsigned char>(tempbuff[2]) << 16)
    | (static_cast<unsigned char>(tempbuff[3]) << 8)
    | static_cast<unsigned char>(tempbuff[4]);

(Измените тип tempbuff на unsigned char[5], и вы можете исключить static_cast.Однако это может потребовать других изменений в других местах.)

Кроме того, второй if почти наверняка должен быть:

if ( bytes_transferred > 4 )

, а не >= (или, альтернативно, >= 5).Или имя не должно быть bytes_transferred.Ваш код получает доступ ко всем пяти байтам tempbuff.(Впрочем, я подозреваю, что если bytes_transferred не совсем 5, все испортится.)

1 голос
/ 03 мая 2011

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

maxsz = *reinterpret_cast<unsigned long*>(&tempBuff[1]);
// or possibly, depending on endianness, ...
maxsz = ntohl(*reinterpret_cast<unsigned long*>(&tempBuff[1]));

Разница в том, что использование memcpy в том виде, в котором ваш код соответствует стандартам, тогда какиспользование reinterpret_cast, как показано здесь, вызывает неопределенное поведение .

0 голосов
/ 03 мая 2011

Я думаю, что первые 4 байта tempbuff размером буфера, поэтому он читает первые 4 байта, определяет размер буфера и затем изменяет размер буфера до этого размера.Выполнение этого в reinterpret_cast, например, в ildjarn, сделает его более похожим на C ++.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...