【发布时间】:2017-02-14 17:13:54
【问题描述】:
我正在将可用的 PoissonRecon 代码 here 集成到我自己的网格操作代码中,但由于 Poisson 中的每个位移指令中的“非法指令”错误,我无法在 x64 中编译集成代码代码的八叉树生成。
我使用的是 Visual Studio 2015,我的问题仅在 x64 中编译且仅在发布模式下才会出现(即,它适用于 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> 一切,但这不是溢出问题。更奇怪的是,如果我在移位之前中断(在发布模式下)然后突出显示操作,调试器会告诉我正确的结果(例如,_startAndWidth 中的d = 5,所以1 << d 在调试器),但实际上单步执行操作会导致“非法指令”错误。
由于程序在调试模式下正常工作,我尝试在发布模式下删除所有优化,但仍然遇到相同的错误。我发现的唯一解决方法是用pow() 替换所有位移操作,虽然这样可行,但bit 似乎很荒谬。
【问题讨论】:
-
欢迎来到 Stack Overflow。请花时间阅读The Tour 并参考Help Center 中的材料,您可以在这里询问什么以及如何询问。
-
可能是无声代码生成错误,从您描述的症状来看,这听起来很合理。我建议您继续升级到 MSVC14.1 和 Visual Studio 2017 RC 或 MSVC14 和 Visual Studio 2015。请注意,Visual Studio 2017 将很快发布,从 RC 升级不应该是一件麻烦事。很棒的新安装程序真的值得,它速度更快,并且包含更好的编译器。
-
我刚刚检查并意识到我说错了。我使用的是 MSVC 2015,而不是 2010。我已经编辑了帖子。
-
此时我将逐步完成程序集。
-
@A.Comer:TBH,我不明白你如何获得积分常数表达式的汇编。即使在调试模式下,编译器本身也应该对此进行全面评估。这是不可避免的,因为
OctNode< NodeData >::DepthMask必须可以用作例如char buf[OctNode< NodeData >::DepthMask]即使在调试模式下也需要编译时常量。
标签: c++ bit-shift illegal-instruction