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
是复制多远的字节数until,out
是开始复制到的内存地址。
当然也可以手动完成,比如
#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),所以很难判断是否 所有内容 都被复制了,或者只是一部分。也就是说,我几乎可以肯定它并没有抓住一切。
对比对应的VideoCallback
和copy(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 的是互斥体的锁定。
考虑到由于缓冲区末尾 运行 导致您有未定义的行为,我很想说这与它有关。
我正在寻找关于为什么会中断的意见。有关上下文信息,请参阅附录,但我真的认为它不相关。
我有一个 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
是复制多远的字节数until,out
是开始复制到的内存地址。
当然也可以手动完成,比如
#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),所以很难判断是否 所有内容 都被复制了,或者只是一部分。也就是说,我几乎可以肯定它并没有抓住一切。
对比对应的VideoCallback
和copy(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 的是互斥体的锁定。
考虑到由于缓冲区末尾 运行 导致您有未定义的行为,我很想说这与它有关。