4

ここで入手可能な PoissonRecon コードを独自のメッシュ操作コードに統合していますが、ポアソン コードの octree 生成のすべてのビット シフト命令で「不正な命令」エラーが発生したため、統合されたコードを x64 でコンパイルできませんでした。

Visual Studio 2015 を使用していますが、問題は x64 でコンパイルされ、リリース モードでのみ発生します (つまり、x86 デバッグとリリース、および x64 デバッグで動作します)。

ビットシフト命令の 1 つの例として、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>すべてを試しましたが、オーバーフローの問題ではありません。さらに奇妙なことに、ビットシフトの前に (リリースモードで) ブレークしてから操作を強調表示すると、デバッガーは正しい結果を教えてくれます (たとえば、デバッガーd = 5では 32_startAndWidth1 << d返します) が、実際に操作をステップオーバーすると、 「不正な命令」エラー。

プログラムはデバッグ モードで正しく動作するため、リリース モードですべての最適化を削除しようとしましたが、それでも同じエラーが発生します。私が見つけた唯一の回避策は、すべてのビットシフト操作をpow()代わりに置き換えることです。それは機能しますが、bitばかげているようです。

4

1 に答える 1