std::copy runtime_error 与 uint16_t 合作时

std::copy runtime_error when working with uint16_t's

我正在寻找关于为什么会中断的意见。有关上下文信息,请参阅附录,但我真的认为它不相关。

我有一个 std::vector<uint16_t> depth_buffer 被初始化为有 640*480 个元素。这意味着它占用的总数space是640*480*sizeof(uint16_t) = 614400.

破解的代码:

void Kinect360::DepthCallback(void* _depth, uint32_t timestamp) {
    lock_guard<mutex> depth_data_lock(depth_mutex);

    uint16_t* depth = static_cast<uint16_t*>(_depth);
    std::copy(depth, depth + depthBufferSize(), depth_buffer.begin());/// the error
    new_depth_frame = true;
}

其中 depthBufferSize() 将 return 614400(我已多次验证)。

我对std::copy(first, amount, out)的理解是first指定开始复制的内存地址,amount是复制多远的字节数untilout是开始复制到的内存地址。

当然也可以手动完成,比如

#pragma unroll
for(auto i = 0; i < 640*480; ++i) depth_buffer[i] = depth[i];

而不是调用 std::copy,但我真的很困惑为什么 std::copy 在这里失败。有什么想法吗???


附录:上下文是我正在编写一个继承自 FreenectDevice 的派生 class 以与 Kinect 360 一起使用。官方错误是 Bus Error,但我'我几乎可以肯定这是因为 libfreenect 将 DepthCallback 中的错误解释为 Bus Error。通过 lldb,这是从 std::copy 抛出的标准 runtime_error。如果我手动输入 depth + 614400 它会崩溃,但如果我有 depth + (640*480) 它会继续运行。在这个阶段,我没有对深度数据做一些有意义的事情(使用 OpenGL 适当地 渲染原始深度 是一个单独的问题 xD),所以很难判断是否 所有内容 都被复制了,或者只是一部分。也就是说,我几乎可以肯定它并没有抓住一切。

对比对应的VideoCallbackcopy(video, video + videoBufferSize(), video_buffer.begin())里面的调用,我不明白上面为什么会崩溃。如果我对 std::copy 的理解是错误的,那么这也应该崩溃,因为 videoBufferSize() 将变为 return 640*480*3*sizeof(uint8_t) = 640*480*3 = 921600*3 是因为我们每个像素有 3 个 uint8_t,RGB(无 A)。 VideoCallback 工作流畅,已通过 OpenGL 验证(事实上它与 libfreenect 提供的样本基本相同......)。仅供参考 none 我发现的样本实际上直接使用原始深度数据,所有样本都对深度进行着色并使用 std::vector<uint8_t> 和 RGB 通道,这不符合我对这个项目的需求。


我很高兴忽略它并在某种意义上继续前进,因为我可以让它工作,但我真的很困惑为什么它会中断。感谢您的任何想法!

std::copy 的工作方式是您提供输入序列的起点和终点以及开始复制到的位置。您提供的终点不在序列的末尾,因为您的 depthBufferSize 函数给出了以字节为单位的偏移量,而不是序列中元素的数量。

如果您删除乘以 sizeof(uint16_t),它将起作用。那时,您也可以考虑改为调用 std::copy_n,这会获取要复制的元素数。

编辑:我刚刚意识到我没有直接回答问题。 根据我对 std::copy 的理解,它不应该对您提供的输入抛出异常。该代码中唯一可以抛出 runtime_error 的是互斥体的锁定。 考虑到由于缓冲区末尾 运行 导致您有未定义的行为,我很想说这与它有关。