擦除时断言的字符串问题

时间:2011-05-29 02:52:20

标签: c++

我正在使用字符串容器在C ++中开发一个程序,就像在std :: string中存储来自套接字的网络数据一样(这很好),我一次最多可以接收1452字节的数据帧,该协议使用包含有关数据包长度的数据区部分的信息的标头,并且标头是固定的20字节长度。我的问题是,一个字符串给了我一个未知的调试断言,因为它断言,但是我没有得到关于该字符串的消息。现在考虑到我可以在任何时间在帧中接收多个数据包,我将所有接收到的数据放入字符串中,将reinterpret_cast放入我的数据结构中,计算数据包的总长度,然后将数据包的数据部分复制到用于正则表达式处理的字符串,此时我执行string.erase,如mybuff.Erase(totalPackLen); <〜这就是调用assert,但是totalpacklen小于字符串大小。

我在这里缺少一些约定吗?或者std :: string真的是不合适的选择吗? TY。

我自己修复了它。使用几个C调用滚动我自己的非常简单的缓冲区:)

int ret = recv(socket,m_buff,0);
if(ret > 0)
{
    BigBuff.append(m_buff,ret);

    while(BigBuff.size() > 16){
        Header *hdr = reinterpret_cast<Header*>(&BigBuff[0]);
        if(ntohs(hdr->PackLen) <= BigBuff.size() - 20){
            hdr->PackLen = ntohs(hdr->PackLen);
            string lData;
            lData.append(BigBuff.begin() + 20,BigBuff.begin() + 20 + hdr->PackLen);
            Parse(lData); //regex parsing helper function
            BigBuff.erase(hdr->PackLen + 20); //assert here when len is packlen is 235 and string len is 1458;
        }
    }
}

2 个答案:

答案 0 :(得分:2)

从您提供的代码段中可以看出,您的数据包包含一个固定长度的二进制标头,后跟一个可变长度的ASCII字符串作为有效负载。你的第一个错误就在这里:

BigBuff.append(m_buff,ret);

这里至少有两个问题:
 1.为什么追加?你可能已经发送了以前的任何消息。你应该从干净的石板开始  2.混合二进制和字符串数据可以工作,但通常不会。通常最好将二进制和ASCII数据分开。不要将std :: string用于非字符串数据。

追加将数据添加到字符串的末尾。追加后的下一个声明是对16的长度的测试,它告诉我你应该重新开始。同样,你可以重新解释BigBuff [0]中的强制转换:

Header *hdr = reinterpret_cast<Header*>(&BigBuff[0]);

由于您使用了append,因此您将永久处理收到的第一个数据包中的标头而不是当前数据包。最后,就是擦除:

BigBuff.erase(hdr->PackLen + 20);

这里有很多问题:
  - 如果数据包长度和recv的返回值是一致的,则第一次调用将不执行任何操作(擦除处于但不超过字符串的结尾)。
  - 如果数据包长度和recv的返回值不一致,则会出现问题。例如,这可能意味着需要多个物理帧来形成一个逻辑帧,这反过来意味着你需要回到原点。
  - 假设物理和逻辑框架是同一个,你仍然会发现这一切都是错误的。如上所述,你第一次正在擦除任何东西。在循环开始时附加的内容正是您不想做的事情。

序列化通常是一个低级概念,最好这样处理。

答案 1 :(得分:0)

您的评论没有意义:

    BigBuff.erase(hdr->PackLen + 20); //assert here when len is packlen is 235 and string len is 1458;

BigBuff.erase(hdr->PackLen + 20)将从hdr->PackLen + 20开始擦除,直到字符串结束。从代码的描述 - 在我看来,你正在删除超出内容数据的结尾。 Here's the reference for std::string::erase()对你而言。

毋庸置疑std::string在这里完全不合适,应该是std::vector