【问题标题】:Cast buffer to pointer Structure将缓冲区转换为指针结构
【发布时间】:2021-03-13 15:33:42
【问题描述】:

我有两个结构

struct TbtStreamHeader
{
    short MsgLen;
    short StreamId;
    int SeqNo;

    TbtStreamHeader()
    {
        MsgLen = StreamId = 0;
        SeqNo = 0;
    }
};

struct Multicast_OrderMsg
{
    char MsgType; ///'N', 'X', 'M'
    long long Timestamp;
    double OrderId;
    int Token;
    char OrderType;
    int Price;
    int Quantity;
    string ToString()
    {
        std::stringstream ss;
        ss<<MsgType<<'|'<<Timestamp<<'|'<<(long long)OrderId<<"|0|"<<Token<<'|'<<OrderType<<'|'<<Price<<'|'<<Quantity;
        return ss.str();
    }

};

我正在使用 ifstream 读取文件,将该文件填充到结构对象中,因为文件不是结构格式,然后将结构复制到 char 缓冲区中。这是更好理解的代码。

TbtStreamHeader hdr;
Multicast_OrderMsg oMsg;
hdr.MsgLen = 38;
hdr.StreamId = streamID;
hdr.SeqNo = 0;
bool firstLine = true;
    while(ifs1)
    {
        if (!getline(ifs1, str1)) break;
        istringstream ss(str1);
        v1.clear();
        while(ss)
        {
            string s1;
            if(!getline( ss, s1, '|' ))
            {
                break;
            }
            v1.push_back(s1);
        }
        if(firstLine)
        {
            firstLine = false;
            seq = atoi(v1[1].c_str());
            hdr.SeqNo = seq;
            getline(ifs1, str1);
        }
        else
        {
            char tempData[38];
            int tempBufOffset=0;
            hdr.SeqNo++;
            oMsg.OrderId = atoll(v1[0].c_str());
            oMsg.Token = atoi(v1[1].c_str());
            oMsg.OrderType = v1[2][0];
            oMsg.Price = atoi(v1[3].c_str());
            oMsg.Quantity = atoi(v1[4].c_str());
            oMsg.MsgType = 'N';
            memcpy(tempData, &hdr, 8);
            tempBufOffset += 8;
            memcpy(tempData+tempBufOffset, oMsg, 30);
            Multicast_OrderMsg* oMsgT = (Multicast_OrderMsg*)tempData+8; //Not able to caste
            cout<<oMsgT->ToString()<<endl;
            tempBufOffset += 30;
            mcastTbt.streams[0].RecoveryPacket(tempData);
        }
    }

这里cout&lt;&lt; 显示分段错误。我无法理解这是什么问题..?

【问题讨论】:

  • 不要粗鲁,但我觉得这是对指针转换的一种混乱和危险的使用。为什么不使用适当的结构数组来存储结构而不是 char 数组?

标签: c++ pointers casting structure


【解决方案1】:

tempData+8 位置没有Multicast_OrderMsg 对象,取消引用此类指针是未定义的行为,因为它违反了严格的别名规则。

但这本身不会通常导致分段。错误,原因是tempData 不足以存储别名Multicast_OrderMsg 对象。在大多数实现中,类型需要至少与其大小对齐,这会导致填充:

struct Multicast_OrderMsg
{
    char MsgType; //        1
    // Padding              7
    long long Timestamp;//  8
    double OrderId;//       8
    int Token;//            4
    char OrderType;//       1
    // Padding              3
    int Price;//            4
    int Quantity;//         4
};

使结构长度为 40 个字节,您只有 30 个字节的空间。因此打印会尝试访问不属于您的内存位置,因此会出现段错误。

【讨论】:

  • 我已经使用了 tempData 大小高达 1024 字节的结果仍然相同
  • 然后调试你的代码,看看究竟是什么导致了异常。底线是演员仍然是UB,不要这样做。如果您需要更多帮助,请发帖 minimal reproducible example 并解释为什么需要像以前那样编写它。
  • oMsgT->MsgType 是显示 seg 错误的第一个要打印的东西
  • 是的,这是可能的,强制转换是未定义的行为,你不能取消引用指针,就这么简单。
猜你喜欢
  • 2018-04-19
  • 1970-01-01
  • 2015-01-31
  • 2019-02-08
  • 2015-04-15
  • 2013-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多