【问题标题】:c++ can not get value from mapc ++无法从地图中获取价值
【发布时间】:2019-11-10 08:51:30
【问题描述】:

我已经实现了一个序列化器来通过网络发送数据。我已经实现了一个可以反序列化原始数据的系统,字符串,map(string,string),map(string,float),但是当反序列化的map用于从钥匙。在调试器中,我可以看到 map 接收到正确的值,但是当我尝试获取数据时,我收到错误“std::out_of_range at memory location”。

这是我的代码

#include <stdint.h>
#include <memory>
#include <string>
#include <map>
#include <algorithm>

#define STREAM_ENDIANNESS 0
#define PLATFORM_ENDIANNESS 0

using namespace std;

class OutputMemoryStream
{
void ReallocBuffer(uint32_t inNewLength)
{
    mBuffer = static_cast<char*>(std::realloc(mBuffer, inNewLength));
    mCapacity = inNewLength;
}

char*       mBuffer = nullptr;
uint32_t    mHead;
uint32_t    mCapacity;
public:
OutputMemoryStream() : mHead(0) { ReallocBuffer(32); }

~OutputMemoryStream()
{
    if (mBuffer) { mBuffer = nullptr; }
}

char*       GetBufferPtr()  const { return mBuffer; }
uint32_t    GetLength()     const { return mHead; }

void        Write(const void* inData, size_t inByteCount)
{
    //make sure we have space...
    uint32_t resultHead = mHead + static_cast<uint32_t>(inByteCount);
    if (resultHead > mCapacity)
    {
        ReallocBuffer(std::max(mCapacity * 2, resultHead));
    }

    //copy into buffer at head
    std::memcpy(mBuffer + mHead, inData, inByteCount);

    //increment head for next write
    mHead = resultHead;
}

template< typename T > void Write(T inData)
{
    static_assert(std::is_arithmetic< T >::value || std::is_enum< T >::value, "Generic Write only supports primitive data types");

    if (STREAM_ENDIANNESS == PLATFORM_ENDIANNESS)
    {
        Write(&inData, sizeof(inData));
    }
    else {  }
}

template< typename T >
void Write(const std::map< string, T >& inMap)
{
    uint32_t elementCount = inMap.size();
    Write(elementCount);
    for (std::pair<string, T> element : inMap)
    {
        Write(element.first);
        Write(element.second);
    }
}

void Write(const std::string& inString)
{
    size_t elementCount = inString.size();
    Write(elementCount + 1);
    Write(inString.data(), (elementCount + 1) * sizeof(char));
}
};

class InputMemoryStream
{
private:
char*       mBuffer;
uint32_t    mHead;
uint32_t    mCapacity;

public:
InputMemoryStream() {}
InputMemoryStream(char* inBuffer, uint32_t inByteCount) : mBuffer(inBuffer), mCapacity(inByteCount), mHead(0) { }

~InputMemoryStream()
{
    if (mBuffer) { mBuffer = nullptr; }
}

uint32_t        GetRemainingDataSize() const 
{
    return mCapacity - mHead;
}

void Read(void* outData, uint32_t inByteCount)
{
    uint32_t resultHead = mHead + inByteCount;
    if (resultHead > mCapacity)
    {
        //handle error, no data to read!
        //...
    }

    std::memcpy(outData, mBuffer + mHead, inByteCount);

    mHead = resultHead;
}


template< typename T > void Read(T& outData)
{
    static_assert(std::is_arithmetic< T >::value || std::is_enum< T >::value, "Generic Read only supports primitive data types");
    Read(&outData, sizeof(outData));
}

template<typename T1>
void Read(std::map<string, T1> &mapP)
{
    size_t elemenCount;
    Read(elemenCount);
    for (int i = 0; i < elemenCount; i++)
    {
        string key; T1 value;
        Read(key);
        Read(value);
        std::pair<string, T1> pair(key, value);
        mapP.insert(pair);
    }
}

void Read(string &outString)
{
    size_t strSize;
    Read(strSize);
    outString.resize(strSize);
    for (int i = 0; i < strSize; i++)
    {
        Read(&outString[i], 1);
    }
}
};

class ServerObject
{
OutputMemoryStream outStream;
InputMemoryStream inStream;
map<std::string, int> mapInt;
public:
ServerObject() {};
ServerObject(char* byteArray, int byteCount)
{
    InputMemoryStream inStream(byteArray, byteCount);
    Deserialize(inStream);
}
~ServerObject() {};

void Serialize()
{
    outStream.Write(mapInt);
}

void Deserialize(InputMemoryStream inStream)
{
    inStream.Read(mapInt);
}

OutputMemoryStream GetOutStream()
{
    return outStream;
}

int GetInt(string key)
{
    return mapInt.at(key);
}

void PutInt(string key, int value)
{
    mapInt.insert(std::pair<string, int>(key, value));
}
};

int main()
{
ServerObject * so = new ServerObject();
so->PutInt("test", 10);
so->Serialize();
ServerObject * so1 = new ServerObject(so->GetOutStream().GetBufferPtr(), so->GetOutStream().GetLength());
int i = so1->GetInt("test");
system("pause>NULL");
return 0;
}

【问题讨论】:

标签: c++ dictionary


【解决方案1】:

OutputMemoryStreamvoid Write(const std::string&amp; inString) 函数不应为空终止符存储额外的缓冲区字节,因为 std::string 将不包含空终止符,但如果您使用 c_str(),则此返回中将包含空终止符方法。不要对内存的内部结构感到困惑。 std::string 将字符串的长度存储在其成员变量中,因此不需要空终止符。函数应该如下所示。

void Write(const std::string& inString)
{
    size_t elementCount = inString.size();
    Write(elementCount);
    Write(inString.data(), elementCount * sizeof(char));
}

【讨论】:

  • 这行得通,但为什么 map(string, float) 没有发生此错误?
  • @Lirus 它应该发生在任何类型上。但是为了检查和解释给你,你还没有发布浮点类型的代码。如果您认为上述答案已经回答了您提出的问题,请接受它作为答案。这也将有助于其他人专注于未回答的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-22
相关资源
最近更新 更多