【问题标题】:Loosing pointer after reading bytes [closed]读取字节后丢失指针[关闭]
【发布时间】:2019-08-28 20:49:33
【问题描述】:

我正在做一个项目,从接收到的字节构造对象 MyClass。字节串由一个整数(4 个字节)和一个消息(5 个字节)组成。

我创建了一个模板类,以便能够轻松读取多种类型,还编写了一个模板特化函数来处理 char 数组的情况。

这是可复制粘贴到 main.cpp 文件中的代码。

#include <algorithm>
#include <cstring>
#include <iostream>
#include <string>

template <typename T>
class ByteReaderT {
    public:

    static const char* read(const char* source, T& dest, size_t sz)
    {
            std::copy(source, source + sz, &dest);
            return source + sz;
        }

};

template<>
inline const char* ByteReaderT<char*>::read(const char* source, char*& dest, size_t sz)
{
    return std::copy(source, source + sz, dest);
}


#define DATA_SIZE 5

struct MyClass {

    int num;
    char* data;

    MyClass(): num(0), data(new char[DATA_SIZE]) {}

    void read(const char* str) {
        // data is still alive and well
        str = ByteReaderT<int>::read(str, num, sizeof(int));
        // data is gone (data = nullptr)
        // I need to reallocate memory with data = new char[DATA_SIZE];
        str = ByteReaderT<char*>::read(str, data, DATA_SIZE);
    }

};



int main()
{
    char received_arr[] = {
        '\x01', '\0', '\0', '\0', // bytes for num
        'r', 'e', 'c', 'v', ' ' // bytes for data
    };

    MyClass c;
    char* ptr = nullptr;

    c.read(received_arr);
    std::cout << c.num << std::endl;
    std::cout << std::string(c.data) << std::endl;

    return 0;
}


但是在MyClass::read 函数中,我的数据指针在读取数字的前 4 个字节后重置为 nullptr。

而且我不知道为什么会这样。模板函数ByteReaderT&lt;int&gt;::read 不应触及数据指针。

我总是可以在读取 5 字节消息之前再次为 MyClass::read 中的数据分配内存,但这并不干净,因为我不应该这样做。

如果有人看到哪里出了问题,将不胜感激,因为我现在陷入困境。

【问题讨论】:

  • 是否有任何不赞成投票的人参与其中,原因是什么?至少,这个问题有minimal reproducible example,现在在SO上很少见。
  • 我首先将代码分成不同的块,然后意识到如果有人想编译它,复制粘贴会很痛苦。大概就是这个原因。
  • 但是,它仍然可以通过 minimal reproducible example.. 我知道由于缺少 minimal reproducible example,我很快就会平局、投反对票和骂人,但你的例子看起来好的。显然,有些人在否决按钮上比我更快:/
  • @AlgirdasPreidžius 这不是最小的。它包含很多不相关的代码。
  • @L.F.如果您知道问题出在哪里,您可以创建minimal reproducible example,这只会产生上述问题。但是,到那时 - 你已经知道答案了,不需要问任何问题。

标签: c++ pointers templates null byte


【解决方案1】:

您将std::copystd::memcpy 混淆了。

std::copy 是来自&lt;algorithm&gt; 库的算法,它以一对迭代器作为源,一个迭代器作为输出。它将简单地遍历源范围中的每个元素,并在以output 开头的范围内复制构造它们。

因为您提供了int 作为输出,所以您只能编写单个元素。更进一步的是未定义的行为(在您的情况下,它似乎覆盖了data 成员)。

std::copy 的示例用法:

std::vector<int> a {1, 2, 3, 4, 5};
std::array<int, 5> b;
for(int n: b)
    std::cout << n << " "; //0 0 0 0 0
std::copy(a.begin(), a.end(), b.begin());
for(int n: b)
    std::cout << n << " "; //1 2 3 4 5

另一方面,std::memcpy 将简单地将内存的内容放在给定位置并放入另一个位置,这就是您想要实现的目标。

示例用法:

int a = 5;
char[4] b;
std::memcpy(b, &a, 4);

【讨论】:

  • 用答案打败我。尽管我知道这一定是 UB,但我脑子里放了很多屁,至于它的原因。必须通过std::copy 进行调试,同时打开内存窗口,才能注意到它:/
  • @AlgirdasPreidžius 有同样的问题:D std::copy 在这里看起来很好
  • 它与 std::memcpy 的作用就像一个魅力。非常感谢
猜你喜欢
  • 1970-01-01
  • 2015-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-29
  • 1970-01-01
  • 2013-04-17
相关资源
最近更新 更多