对我来说没有意义的memcpy

时间:2011-05-03 08:37:12

标签: c++ sockets boost-asio

我有一些套接字连接代码,它使用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 个答案:

答案 0 :(得分:4)

此代码告诉您所需缓冲区的大小。

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

此代码正在调整缓冲区的大小

buff.resize(maxsz);

答案 1 :(得分:2)

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,事情会搞砸。)

答案 2 :(得分:1)

该代码与以下内容基本相同,我认为您看起来比较熟悉:

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

不同之处在于,以您的代码执行方式使用memcpy符合标准,而使用此处所示的reinterpret_cast会调用undefined behavior

答案 3 :(得分:0)

我认为tempbuff的前4个字节是缓冲区的大小,因此它读取前4个字节,确定缓冲区的大小,然后将缓冲区的大小调整为该大小。在像ildjarn这样的reinterpret_cast中执行此操作将使其更像C ++。