【问题标题】:serialize and deserialize datas with reinterpret_cast使用 reinterpret_cast 序列化和反序列化数据
【发布时间】:2017-04-11 09:46:59
【问题描述】:

我尝试做一些简单的事情:我有 2 个函数,第一个生成 2 个 char 数组和 1 个 int 然后将它们连接起来,将它们重新解释为 void* 并返回它。

第二个将其重新解释为char* 并打印出来。 问题是:如果我将它重新解释为 char* 并在 void* 转换之后打印它(在同一个函数中),它工作得很好,但在反序列化函数中却不行。

这是我的代码:

#include <sstream>
#include <unistd.h>

void * serialize( void )
{
    char s1[9];
    char s2[9];
    int  n;
    std::string alphanum = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

    s1[8] = '\0';
    s2[8] = '\0';

    for (int i = 0; i < 8; i++)
    {
        usleep(1);
        s1[i] = alphanum[clock() % (alphanum.length() - 1)];
    }
    n = clock() % 2147483647;
    for (int i = 0; i < 8; i++)
    {
        usleep(1);
        s2[i] = alphanum[clock() % (alphanum.length() - 1)];
    }

    std::cout << "s1: " << s1 << std::endl;
    std::cout << "n: " << n << std::endl;
    std::cout << "s2: " << s2 << std::endl;

    std::stringstream ss;
    std::string str;
    ss << s1 << n << s2;
    ss >> str;

    char * c = const_cast<char*>(str.c_str());
    void * d = reinterpret_cast<void*>(c);
    std::cout << reinterpret_cast<char*>(d) << std::endl; // HERE IT WORKS
    return d;
}

void deserialize( void * raw )
{
    char* c = reinterpret_cast<char*>(raw);
    std::cout << c << std::endl; //HERE IT DOESN'T WORK
}

int     main(void)
{
    void* serialized = serialize();
    deserialize(serialized);

    return 0;
}

我的输出如下:

s1: 6dfhkmoq n: 1857 s2: tyADFHKM 6dfhkmoq1857tyADFHKM 6�c2X� d2X�

如何才能获得相同的输出?

【问题讨论】:

  • 变量 str 在堆栈上,您实际上是在返回一个指向其内部缓冲区的指针。只要你在 serialize 函数中,一切都很好(str 仍然存在),但是一旦你离开 serialize 函数,str 变量就会被释放,你现在正在访问释放的内存,你可以期待的最好的就是垃圾
  • 哦,是的,当我在堆上分配它时效果更好,谢谢。

标签: c++ casting reinterpret-cast


【解决方案1】:

那是因为您正在返回一个指向 string 对象内存的指针(具有自动存储功能)。来自cppeference

返回值

指向底层字符存储的指针。

当堆栈展开时,分配给字符串的内存会被覆盖(其内部缓冲区也是如此)。当块由于异常或到达控制流的末尾时会发生这种情况。

阅读What is stack unwinding?

为了确保您的内存位置仍然有效,您必须在堆上分配它。您可以创建一个 shared_ptr 并返回它。

但是 reinterpret_cast 经常闻起来像是糟糕的设计,所以您可能需要重新考虑为什么要将类型隐藏在 void* 后面

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-18
    • 1970-01-01
    • 2014-03-19
    • 2012-03-17
    相关资源
    最近更新 更多