【问题标题】:Memcpy unique_ptr to vectorMemcpy unique_ptr 到向量
【发布时间】:2021-05-16 02:17:03
【问题描述】:

我正在尝试将 unique_ptr 缓冲区uint32_t bufferSize 描述的内存区域写入 std::vector 值。当我为此使用 std::memcpy 时,我收到以下警告:

‘void* memcpy(void*, const void*, size_t)’ 写入类型为 ‘class std::vector’ 的对象,没有简单的复制赋值;使用复制分配或复制初始化 [-Wclass-memaccess]

int ReadByName (std::vector<unsigned char> &value, const char handleName[], std::ostream &out, const long &port, const AmsAddr &server)
{
        uint32_t bytesRead;

        out << __FUNCTION__ << "():  ";
        
        if (this->handle == 0)
            handle = getHandleByName(out, port, server, handleName);
        if (bufferSize == 0)
            bufferSize = getSymbolSize(out, port, server, handleName);

        const auto buffer = std::unique_ptr<uint8_t>(new uint8_t[bufferSize]);

        const long status = AdsSyncReadReqEx2(  port,
                                                &server,
                                                ADSIGRP_SYM_VALBYHND,
                                                handle,
                                                bufferSize,
                                                buffer.get(),
                                                &bytesRead);
        
        if (status) {
            out << "ADS read failed with: " << std::dec << status << '\n';
            return 2;
        }
        value.clear();
        value.reserve(bufferSize);
        std::memcpy(&value, buffer.get(), bufferSize);
        return 0;
}

解决问题的正确方法是什么?

问候 蒂尔曼

【问题讨论】:

  • value.assign(buffer.get(), buffer.get() + bufferSize);?
  • 离题但是... buffer 应该使用std::unique_ptr&lt;uint8_t[]&gt;(new uint8_t[bufferSize]) 而不是std::unique_ptr&lt;uint8_t&gt;(new uint8_t[bufferSize]) 进行初始化——注意额外的[]
  • 谢谢,我想这就是我要找的@Jarod42。

标签: c++ stdvector unique-ptr memcpy


【解决方案1】:

解决问题的正确方法是什么?

这将是直接读入向量,而不是稍后复制的单独数组。

如果使用 AdsSyncReadReqEx2() 的读取操作失败,值将已被清除。

不要清除value,而是使用另一个向量。如果操作成功,将中间向量移动分配给value,这不需要复制元素。

更好:根本不要将value 传递给函数,而是返回向量并使用比普通错误代码更现代的错误处理机制。您可以使用例如异常或类似于建议的std::expected 的东西。

【讨论】:

  • 似乎问题在于AdsSyncReadReqEx2 期望uint8_t*,但OP 想将其返回为unsigned char
  • @Yksisarvinen 这应该不是问题,因为uint8_tunsigned char 的别名。
  • 这里我看到了一个问题:如果使用 AdsSyncReadReqEx2() 的读取操作失败,则值已经被清除。缓冲区允许我在覆盖存储的值之前等待读取操作的结果。
【解决方案2】:

两个错误,这里是正确的代码

    value.clear();
    value.resize(bufferSize);
    std::memcpy(value.data(), buffer.get(), bufferSize);

第一个错误,&amp;value 没有给你向量的数据区域供你写入value.data() 这样做。

第二个错误,reserve 不会更改向量的大小,因此您正在写入一个空向量。使用resize 更改向量的大小。

编辑

很明显,eerorika 说的是真的。您可以修改上述代码,将指向矢量数据的有效指针传递给AdsSyncReadReqEx2,并完全取消buffer

 value.resize(bufferSize);
 const long status = AdsSyncReadReqEx2(  port,
        &server,
        ADSIGRP_SYM_VALBYHND,
        handle,
        value.size(),
        value.data(),
        &bytesRead);

【讨论】:

    猜你喜欢
    • 2014-07-21
    • 2013-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-21
    • 1970-01-01
    • 2020-05-20
    相关资源
    最近更新 更多