我正在尝试分析我的代码,但遇到了问题。
如果我运行以下代码:
#include <iostream>
int main() {
size_t val = 8;
std::cout << sizeof(val) << std::endl;
std::cout << __builtin_ctz(val) << std::endl;
}
它按预期返回
8
3
如果我在上面运行 valgrind,它会返回:
==28602== Memcheck, a memory error detector
==28602== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==28602== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==28602== Command: ./test
==28602==
8
vex amd64->IR: unhandled instruction bytes: 0xF3 0xF 0xBC 0xC0 0x89 0xC6 0xBF 0x60
==28602== valgrind: Unrecognised instruction at address 0x400890.
==28602== at 0x400890: main (in /home/magu_/sod/test/test)
==28602== Your program just tried to execute an instruction that Valgrind
==28602== did not recognise. There are two possible reasons for this.
==28602== 1. Your program has a bug and erroneously jumped to a non-code
==28602== location. If you are running Memcheck and you just saw a
==28602== warning about a bad jump, it's probably your program's fault.
==28602== 2. The instruction is legitimate but Valgrind doesn't handle it,
==28602== i.e. it's Valgrind's fault. If you think this is the case or
==28602== you are not sure, please let us know and we'll try to fix it.
==28602== Either way, Valgrind will now raise a SIGILL signal which will
==28602== probably kill your program.
==28602==
==28602== Process terminating with default action of signal 4 (SIGILL)
==28602== Illegal opcode at address 0x400890
==28602== at 0x400890: main (in /home/magu_/sod/test/test)
==28602==
==28602== HEAP SUMMARY:
==28602== in use at exit: 0 bytes in 0 blocks
==28602== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==28602==
==28602== All heap blocks were freed -- no leaks are possible
==28602==
==28602== For counts of detected and suppressed errors, rerun with: -v
==28602== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
Illegal instruction (core dumped)
这是 valgrind 的错误还是我不应该在我的计算机上使用 __builtin_ctz
? __builtin_popcount
不会引发任何错误。
我的系统:
g++ (Ubuntu 4.8.1-2ubuntu1~12.04) 4.8.1
CPU : Intel Core Duo T7500
最佳答案
您需要将 valgrind 至少升级到 4.8.1 或使用早于 v4.8 的 gcc。
您遇到的操作码 -- F3 0F BC
-- 是 BMI1 中引入的 TZCNT
操作码,您的 CPU 没有实现它。但是,它也是 REP;BSF
(F3
是REP
)并且旧的 CPU,包括你的,忽略此操作码的 REP
,以及类似的 LZCNT == REP;BSR
对。 TZCNT
和 BSF
之间几乎没有区别(它们在处理 0 的方式上有所不同)。
较旧的 gcc
版本对较旧的 CPU 使用 BSF
,对较新的 CPU 使用 TZCNT
,但由于操作码相对较少,因此在较新的 gcc 版本中逻辑得到了简化,并且始终使用 TZCNT
,因为新旧 CPU 都能理解它。
不幸的是,直到 v4.8.1,valgrind
才正确地从 TZCNT
回退到 BSF
。参见 bug 295808 .
关于c++ - __builtin_ctz 的 valgrind 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25190315/