仅在64位释放模式中的位移位非法指令
bit-shift illegal instruction in 64-bit release mode only
我正在将此处可用的PoissonCon代码集成到我自己的网格操作代码中,但我无法在x64中编译集成代码,因为Poisson代码的八叉树生成中的每个位偏移指令中都存在"非法指令"错误。
我使用的是Visual Studio 2015,只有在x64中编译时,以及只有在发布模式下(即,它在x86调试和发布以及x64调试中工作),才会出现问题。
作为其中一个位移位指令的示例,在Octre.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
在调试器中返回32),但实际上跨接该操作会导致"非法指令"错误。
由于程序在调试模式下正常工作,我尝试在发布模式下删除所有优化,但仍然会出现同样的错误。我找到的唯一解决方法是用pow()
替换所有的位移位操作,尽管这很有效,但它似乎是bit
的荒谬之处。
事实证明,重建代码附带的.sln文件是用AVX2设置的,这在我的机器上是不受支持的。
转到Configuration Properties >> C/C++ >> Code Generation
并将"启用增强指令集"设置为AVX解决了问题。
汇编代码现在显示的是"SHL"而不是"SHLX",因此"非法指令"是实际的SHLX命令不可用,而不是进入SHLX的参数的问题。
- 在 std::string 中使用非法的 UTF-8 八位字节作为分隔符
- C++:无法在按位函数后将 int 类型设置为非标量
- 结构内部的结构:"对非静态成员的非法引用"错误
- UTF-8字符串上的位XOR操作可提供非UTF-8输出
- MEMCMP以相同(零值)位字段结构返回非零
- 建筑物32位openssl fips(nmake f ms ntdll.mak):宏中的非法字符
- 仅在64位释放模式中的位移位非法指令
- 为什么要将XOR与文字而不是反转(非位)使用
- 使用非 32 位整数是否合理
- 如何压缩一个非重复数字大小的N位序列?
- 非连续内部数字表示上的位移位
- 如何将托管位图从 C# 传递到包装的非托管 OpenCV 的 Mat
- 非法调用非静态成员函数
- C2597 非法引用非静态成员
- Visual Studio将非托管的64位DLL复制到SysWOW64,而不是System32
- C++错误 C2352:'CSchedulerDlg::Select':非法调用非静态成员函数
- 寻找非立即移位值的sse 128位移位操作
- 数据库.错误C2352:非法调用非静态成员函数
- C++-按位非uchar产生int
- 当64位非托管代码通过COM调用托管代码时会发生什么