【问题标题】:valgrind: Unrecognised instruction at address 0x5111715valgrind:地址 0x5111715 处无法识别的指令
【发布时间】:2016-09-24 06:53:35
【问题描述】:

我有一个看起来像这样的函数 -

std::string func()
{
    std::string result;

    ...

    auto seed = std::random_device()();
    std::mt19937 gen(seed);
    std::uniform_int_distribution<> dis(0, 61);

    ...
    return result;
}

它可以在各种编译器及其版本中正常编译,但仍然无法通过 Ubuntu 上的 valgrind 测试。我明确提到了 ubuntu,因为它在我安装了 Arch Linux 的机器上成功通过。

两个 valgrind 安装都报告它们的版本为 valgrind-3.11.0,唯一的区别是 Arch Linux 安装在我的机器上,没有虚拟化,而 Ubuntu 测试已经在 DO/CI 服务器上完成,可能处于某种虚拟化状态。但这有关系吗?


这是 valgrind 运行的日志 -

 --- stderr ---
==13849== Memcheck, a memory error detector
==13849== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==13849== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==13849== Command: file/path/here
==13849== 
vex amd64->IR: unhandled instruction bytes: 0xF 0xC7 0xF0 0x89 0x6 0xF 0x42 0xC1
vex amd64->IR:   REX=0 REX.W=0 REX.R=0 REX.X=0 REX.B=0
vex amd64->IR:   VEX=0 VEX.L=0 VEX.nVVVV=0x0 ESC=0F
vex amd64->IR:   PFX.66=0 PFX.F2=0 PFX.F3=0
==13849== valgrind: Unrecognised instruction at address 0x5111715.
==13849==    at 0x5111715: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.22)
==13849==    by 0x51118B1: std::random_device::_M_getval() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.22)
==13849==    by 0x4809FB: std::random_device::operator()() (random.h:1612)
==13849==    by 0x47F0C2: isaac::deviceList::genId[abi:cxx11](unsigned int) (deviceList.cpp:21)
==13849==    by 0x47F2A7: isaac::deviceList::place(isaac::deviceType, nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator>) (deviceList.cpp:38)
==13849==    by 0x40D06E: DeviceList_place_Test::TestBody() (test.cpp:194)
==13849==    by 0x45D5A7: void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (gtest.cc:2078)
==13849==    by 0x4588D2: void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (gtest.cc:2114)
==13849==    by 0x43EBB3: testing::Test::Run() (gtest.cc:2151)
==13849==    by 0x43F3F5: testing::TestInfo::Run() (gtest.cc:2326)
==13849==    by 0x43FA52: testing::TestCase::Run() (gtest.cc:2444)
==13849==    by 0x446911: testing::internal::UnitTestImpl::RunAllTests() (gtest.cc:4315)
==13849== Your program just tried to execute an instruction that Valgrind
==13849== did not recognise.  There are two possible reasons for this.
==13849== 1. Your program has a bug and erroneously jumped to a non-code
==13849==    location.  If you are running Memcheck and you just saw a
==13849==    warning about a bad jump, it's probably your program's fault.
==13849== 2. The instruction is legitimate but Valgrind doesn't handle it,
==13849==    i.e. it's Valgrind's fault.  If you think this is the case or
==13849==    you are not sure, please let us know and we'll try to fix it.
==13849== Either way, Valgrind will now raise a SIGILL signal which will
==13849== probably kill your program.
==13849== 
==13849== Process terminating with default action of signal 4 (SIGILL): dumping core
==13849==  Illegal opcode at address 0x5111715
==13849==    at 0x5111715: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.22)
==13849==    by 0x51118B1: std::random_device::_M_getval() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.22)
==13849==    by 0x4809FB: std::random_device::operator()() (random.h:1612)
==13849==    by 0x47F0C2: isaac::deviceList::genId[abi:cxx11](unsigned int) (deviceList.cpp:21)
==13849==    by 0x47F2A7: isaac::deviceList::place(isaac::deviceType, nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator>) (deviceList.cpp:38)
==13849==    by 0x40D06E: DeviceList_place_Test::TestBody() (test.cpp:194)
==13849==    by 0x45D5A7: void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (gtest.cc:2078)
==13849==    by 0x4588D2: void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (gtest.cc:2114)
==13849==    by 0x43EBB3: testing::Test::Run() (gtest.cc:2151)
==13849==    by 0x43F3F5: testing::TestInfo::Run() (gtest.cc:2326)
==13849==    by 0x43FA52: testing::TestCase::Run() (gtest.cc:2444)
==13849==    by 0x446911: testing::internal::UnitTestImpl::RunAllTests() (gtest.cc:4315)
==13849== 
==13849== HEAP SUMMARY:
==13849==     in use at exit: 84,300 bytes in 108 blocks
==13849==   total heap usage: 622 allocs, 514 frees, 530,112 bytes allocated
==13849== 
==13849== LEAK SUMMARY:
==13849==    definitely lost: 0 bytes in 0 blocks
==13849==    indirectly lost: 0 bytes in 0 blocks
==13849==      possibly lost: 0 bytes in 0 blocks
==13849==    still reachable: 84,300 bytes in 108 blocks
==13849==         suppressed: 0 bytes in 0 blocks
==13849== Rerun with --leak-check=full to see details of leaked memory
==13849== 
==13849== For counts of detected and suppressed errors, rerun with: -v
==13849== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
-------

编辑 - 我也尝试从官方来源手动构建 valgrind 并安装它,但仍然产生相同的错误。

【问题讨论】:

  • 你在 Ubuntu 机器上使用了哪些编译器标志?显然,编译器正在生成一条非法指令。 Ubuntu机器上/proc/cpuinfo的输出是什么?
  • @MartinNyolt 两个版本都有相同的标志,ubuntu /proc/cpuinfo - gist.github.com/agauniyal/c8d57b106097a16296b259b86fc93368
  • 但是 what 到底是什么标志?我正在帮助您找出为什么您的编译器会生成非法指令。您是否调试了代码并检查了它尝试执行的 哪个 指令?错误是仅在 valgrind 期间发生,还是在正常执行期间也会出现 SIGILL?
  • @MartinNyolt 该错误不会在该程序的编译或执行期间出现,仅在 valgrind 执行期间出现。这是我的构建系统传递的所有标志 - "c++ '-Ibenchmark/randIdGen@exe' '-fdiagnostics-color=always' '-I../benchmark' '-Ibenchmark' '-pipe' '-Wall' '-Wpedantic' '-Wextra' '-Winvalid-pch' '-Wnon-virtual-dtor' '-std=c++14' '-O0' '-g' '-MMD' '-MQ' 'benchmark/randIdGen@exe/randomIdGen.cpp.o' '-MF' 'benchmark/randIdGen@exe/randomIdGen.cpp.o.d' -o 'benchmark/randIdGen@exe/randomIdGen.cpp.o' -c ../benchmark/randomIdGen.cpp"
  • @MartinNyolt “您是否调试了代码并检查了它尝试执行的哪个指令?” Valgrind 是一个调试器,是的,指令已经在问题中了:“vex amd64-&gt;IR: unhandled instruction bytes: 0xF 0xC7 0xF0 0x89 0x6 0xF 0x42 0xC1

标签: c++ c++11 random memory-leaks valgrind


【解决方案1】:

https://bugs.kde.org/show_bug.cgi?id=353370

获取/编译最后一个 svn 版本应该可以解决这个问题。

如果没有,请在 bugzilla 上报告此问题,因为 3.12 版本即将发布。 谢谢

【讨论】:

    【解决方案2】:

    看起来你的 Ubuntu 系统有一个随机数库,它使用你的 Valgrind 版本无法识别的 RDRAND 指令(操作码 0x0f 0xc7)。你的 Arch 系统显然使用了一个不同的实现,它没有利用这个指令。

    您可以通过为 Ivy Bridge 之前的 CPU 重新编译来解决此问题。

    【讨论】:

    • 像在我的系统上编译一样重新编译,然后在 CI 构建上下载该二进制文件并在其上运行 valgrind?
    • 看起来该指令在您的 libstdc++ 库中,所以我想您可能需要重新编译它。您还可以检查这是否是 valgrind 的已知问题,并查看是否有任何补丁可以修复它。
    • 嗯,我不能静态链接到它吗?重新编译 libstdc++ 库对我来说似乎不是一天的任务:p
    • 您还可以检查库源代码以查看是否有任何编译时或运行时开关可以让您避免此指令。
    猜你喜欢
    • 2016-08-30
    • 2013-12-02
    • 2012-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-27
    • 2017-06-09
    • 1970-01-01
    相关资源
    最近更新 更多