【问题标题】:Using std::memcpy to copy an object that contains a boost::any data member使用 std::memcpy 复制包含 boost::any 数据成员的对象
【发布时间】:2021-11-28 15:23:20
【问题描述】:

我正在尝试通过网络 API 传递一个包含 boost::any 数据成员的对象,以在两个应用程序之间交换数据。我知道 API 在内部使用 memcpy 来复制数据,但我不确定我想要做的是否是调用未定义的行为。

我写了一个简单的例子来演示以这种方式使用memcpy

#include <boost/any.hpp>
#include <cstring>
#include <string>
#include <iostream>

class Data
{
public:
    template <typename T>
    Data(T value)
        : m_value(value)
    {}

    template <typename T>
    T Read() const
    {
        return boost::any_cast<T>(m_value);
    }

private:
    boost::any m_value;
};

int main()
{
    Data src(std::string("This is some data."));
    std::cout << "Size: " << sizeof(src) << std::endl;
    std::cout << "SRC: " << src.Read<std::string>() << std::endl;

    void* dst = malloc(sizeof(src));
    std::memcpy(dst, &src, sizeof(src));

    const auto data = static_cast<Data*>(dst);
    std::cout << "DST: " << data->Read<std::string>() << std::endl;

    std::free(dst);
}

此代码似乎可以工作,并打印以下输出:

Size: 8
SRC: This is some data.
DST: This is some data.

但是根据Data 对象中存储的类型,大小不会改变吗?无论我使用什么类型,它总是打印大小为8

这段代码是否调用了未定义的行为?如果是,我该如何修复它,以便我可以正确地 memcpy 一个包含 boost::any 数据成员的对象?

【问题讨论】:

  • sizeof ( boost::any) 是一个常数。不管它是什么类型,它总是一样的。
  • 通常你应该永远使用std::memcpy来复制任何C++对象。它将执行逐字节的直接复制,并且不会调用复制构造函数,这意味着可能无法以有效的方式复制复杂的对象。
  • @Someprogrammerdude 在这种情况下我别无选择,因为 memcpy 在网络 API 内部被调用。我只需要确保可以使用memcpy 有效地复制我传递给它的类型
  • 这也是相关的:en.cppreference.com/w/cpp/types/is_trivially_copyable。如果它不是is_trivially_copyable,那么你不能只是 memcpy 它,因为复制它需要的不仅仅是复制位和字节。 any 当然不是。

标签: c++ undefined-behavior memcpy boost-any


【解决方案1】:

any 包含一个指针,并有一个析构函数,总体上是你不想memcpy 的东西。它在这里工作是因为srcdst 都在同一个内存空间中,并且因为您在没有运行析构函数的情况下freeing 对象。

memcpyany 持有的指向对象(any_cast 返回的对象)可能没问题。 memcpy 本身或包含它的对象绝对可以。

【讨论】:

  • 没有双重释放,因为第二个对象不是数据,而是一个指向数据的原始指针,它通过不运行析构函数的std:free 释放。 OP 很幸运,一个 memcpy'd std::string “如果原件没有被破坏并且你不尝试任何有趣的事情,那么它就可以工作。”绝对不会跨进程工作。
  • 很好,我看到了free,想到了delete
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-12
  • 1970-01-01
  • 2021-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-29
相关资源
最近更新 更多