gpt4 book ai didi

c++ - 仅 64 位 Release模式下的移位非法指令

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:10:35 24 4
gpt4 key购买 nike

我正在整合可用的 PoissonRecon 代码 here到我自己的网格操作代码中,但我一直无法在 x64 中编译集成代码,因为泊松代码的八叉树生成中的每个位移位指令都存在“非法指令”错误。

我使用的是 Visual Studio 2015,我的问题仅在 x64 编译且仅在 Release模式下出现(即,它适用于 x86 调试和发布以及 x64 调试)。

作为移位指令之一的示例,以下定义在 Octree.inl 的顶部:

template< class NodeData > const int OctNode< NodeData >::DepthShift=5;
template< class NodeData > const int OctNode< NodeData >::OffsetShift = ( sizeof(long long)*8 - DepthShift ) / 3;
template< class NodeData > const int OctNode< NodeData >::DepthMask=(1<<DepthShift)-1; // This variable is correct
template< class NodeData > const int OctNode< NodeData >::OffsetMask=(1<<OffsetShift)-1; // This variable is also correct
template< class NodeData > const int OctNode< NodeData >::OffsetShift1=DepthShift;
template< class NodeData > const int OctNode< NodeData >::OffsetShift2=OffsetShift1+OffsetShift;
template< class NodeData > const int OctNode< NodeData >::OffsetShift3=OffsetShift2+OffsetShift;

这些变量在下面的函数中使用:

template< class NodeData >
inline unsigned long long OctNode< NodeData >::Index( int depth , const int offset[3] )
{
unsigned long long idx=0;
idx |= ( ( (unsigned long long)(depth ) ) & DepthMask );
idx |= ( ( (unsigned long long)(offset[0]) ) & OffsetMask ) << OffsetShift1;
idx |= ( ( (unsigned long long)(offset[1]) ) & OffsetMask ) << OffsetShift2;
idx |= ( ( (unsigned long long)(offset[2]) ) & OffsetMask ) << OffsetShift3;
return idx;
}

这个函数在行处中断

idx |= ( ( (unsigned long long)(offset[0]) ) & OffsetMask ) << OffsetShift1;

我进一步分解后发现问题出在移位本身,即 (var)<<OffsetShift1;但这会导致“非法指令”错误。

请注意 OffsetShift1 只是“5”,因此这相当于 (var)<<5;这确实按预期工作。

一个可能的解决方法是简单地 #define顶部的所有这些变量(确实解决了问题),但这并没有解决其他移位问题,例如:

void _startAndWidth( const TreeOctNode* node , Point3D< Real >& start , Real& width ) const
{
LocalDepth d ; LocalOffset off;
_localDepthAndOffset( node , d , off );
if (d >= 0) width = Real(1.0 / (1 << d));
else width = Real( 1.0 * (1<<(-d)) );
for( int dd=0 ; dd<DIMENSION ; dd++ ) start[dd] = Real( off[dd] ) * width;
}

我试过 static_cast<long long>一切,但这不是溢出问题。更奇怪的是,如果我在位移前中断(在 Release模式下)然后突出显示操作,调试器会告诉我正确的结果(例如,d = 5_startAndWidth 中,所以 1 << d 在调试器),但实际上跨过操作会导致“非法指令”错误。

由于程序在 Debug模式下运行正常,我尝试在 Release模式下删除所有优化,但我仍然遇到同样的错误。我发现的唯一解决方法是将所有移位操作替换为 pow()相反,虽然它有效,但它似乎是一个 bit可笑。

最佳答案

事实证明,重构代码附带的 .sln 文件是用 AVX2 设置的,我的机器不支持它。

转到 Configuration Properties >> C/C++ >> Code Generation 并将“Enable Enhanced Instruction Set”设置为 AVX 解决了这个问题。

汇编代码现在显示“SHL”而不是“SHLX”,因此“非法指令”是实际的 SHLX 命令不可用,而不是进入 SHLX 的参数的问题。

关于c++ - 仅 64 位 Release模式下的移位非法指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42232218/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com