LoginSignup
1
0

More than 3 years have passed since last update.

Raspberry Pi 上の clang のバグっぽい挙動

Posted at

先日。
Raspberry Pi 上の clang のバグっぽい挙動に遭遇したので報告。

現象

三角関数の計算を間違える。

環境

$ uname -a
Linux raspberrypi 4.19.50-v7+ #896 SMP Thu Jun 20 16:11:44 BST 2019 armv7l GNU/Linux
$ cat /etc/debian_version 
10.0
$ clang --version
clang version 7.0.1-8+rpi1 (tags/RELEASE_701/final)
Target: armv6k-unknown-linux-gnueabihf
Thread model: posix
InstalledDir: /usr/bin
$ apt info clang
Package: clang
Version: 1:7.0-47
Priority: optional
Section: devel
Source: llvm-defaults (0.47)
Maintainer: LLVM Packaging Team <pkg-llvm-team@lists.alioth.debian.org>
Installed-Size: 23.6 kB
Depends: clang-7 (>= 7~)
Breaks: clang-3.2, clang-3.3, clang-3.4 (<< 1:3.4.2-7~exp1), clang-3.5 (<< 1:3.5~+rc1-3~exp1)
Replaces: clang (<< 3.2-1~exp2), clang-3.2, clang-3.3, clang-3.4 (<< 1:3.4.2-7~exp1), clang-3.5 (<< 1:3.5~+rc1-3~exp1)
Download-Size: 7,468 B
APT-Manual-Installed: yes
APT-Sources: http://raspbian.raspberrypi.org/raspbian buster/main armhf Packages
Description: C, C++ and Objective-C compiler (LLVM based)
 Clang project is a C, C++, Objective C and Objective C++ front-end
 for the LLVM compiler. Its goal is to offer a replacement to the GNU Compiler
 Collection (GCC).
 .
 Clang implements all of the ISO C++ 1998, 11 and 14 standards and also
 provides most of the support of C++17.
 .
 This is a dependency package providing the default clang compiler.

再現方法

まずはソースコード:

clangsin.cpp
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstdint>

template< typename t >
void dump( char const * name, t * v )
{
  auto p = reinterpret_cast<std::uint8_t const *>(v);
  std::cout << name << "=";
  for( auto it = p ; it != p+sizeof(*v) ; ++it ){
    std::printf( "%02x ", *it );
  }
  std::cout << "\n";
}

int main()
{
  float f = std::cos( 3.45f );
  double d = std::cos( 3.45 );
  std::cout << "f=" << f << "  d=" << d << std::endl;
  std::printf( "f=%g  d=%g\n", f, d );
  dump("f", &f);
  dump("d", &d);
  return 0;
}

そして実行結果:

$ clang++ -Wall clangsin.cpp && ./a.out
f=-9.32929e-17  d=2.11371e-314
f=3.45  d=6.20896e-312
f=cd cc 5c 40 
d=9a 99 99 99 24 01 00 00
$ g++-8 -Wall clangsin.cpp && ./a.out
f=-0.952818  d=-0.952818
f=-0.952818  d=-0.952818
f=e5 eb 73 bf 
d=98 e6 d6 9f 7c 7d ee bf 

おかしなところ

計算結果

計算結果は、g++-8 のものが正しい。clang の結果は間違っている

ていうか。
f の値なんて、絶対値が 1 を遥かに超えているし、入力の 3.45f そのまんまだし、一体何なんだ。

float と double

floatdouble はほぼ同じ値になるべきだが、そうなっていない

printf と cout

printfcout は同じ変数を参照しているはずなのに、まったく違う値を出している。困る。
ダンプの結果と整合するのは printf の方である。

"cd cc 5c 40".split(" ").map{|e|e.to_i(16).chr}.join.unpack("f")
#=> [3.450000047683716]
"9a 99 99 99 24 01 00 00".split(" ").map{|e|e.to_i(16).chr}.join.unpack("d")
#=> [6.208959684366e-312]

原因

さっぱりわからない

対策

当面は Raspberry Pi 上で clang を使うのをやめることにした。

1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0