Yabu.log

ITなどの雑記

gdbを使ってsegmentation faultを調べる

いきなりsegmentation fault (core dump)と端末に表示されて異常終了をするプログラムに頭を悩まされていました。

...(順調に処理中)...
/home/yuyabu/3d/bin/02.sh: 42 行: 58161 浮動小数点例外   (コアダンプ) openMVG/Linux-x86_64-RELEASE/openMVG_main_IncrementalSfM -i result/sfm_data.json -m matches -o out

C/C++Linuxな環境であり、かつ自分で作ったファイルまたはオープンソースなどでバイナリに対応したファイルが用意できれば、gdbを使ってエラーが発生している箇所がわかるかもしれません。

ちなみに今回の対象ソースはOpenMVGという3Dを処理するOSSです。

1.core fileが作成されるように設定する

Unix系のOSではプログラムが異常終了したときにメモリなどの情報を「corefile」として吐き出す機能があります。 こちらはデフォルトの状態では出力サイズが制限されており作成されないようになっているので、ulimit -c unlimitedで corefileを無制限に作成できるように設定します。

 ulimit -a
core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 4124107
max locked memory       (kbytes, -l) unlimited
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 4124107
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

これでcoredump発生時に実行時のカレントディレクトリにcorefileが作成されるようになります。

2.セグメンテーションフォルトが発生するプログラムをDEBUGビルドする

エラーが発生しているバイナリのソースをデバッグビルドします デバッグビルドができるようなオプションをつけてビルドツールを実行してください。 こちらは調査対象のアプリやビルドツールによって色々なので各自調べてください。

今回私が調査したopenMVGの場合は以下ビルド方法の「3.Configure and build」のオプション-DCMAKE_BUILD_TYPEをRELEASEからDEBUGに変えるだけです。

github.com

$ cmake -DCMAKE_BUILD_TYPE=DEBUG ../openMVG/src/
$ cmake --build . --target install

3.gdbで調べる

gdb <実行バイナリ> <corefile>
gdb ../build/openMVG/Linux-x86_64-DEBUG/openMVG_main_IncrementalSfM ./core 
GNU gdb (Ubuntu 8.1-0ubuntu3) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ../build/openMVG/Linux-x86_64-DEBUG/openMVG_main_IncrementalSfM...
done.

warning: core file may not match specified executable file.
[New LWP 58245]
...(略)...
[New LWP 58268]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `/home/yuyabu/3d/build/openMVG/Linux-x86_64-DEBUG/openMVG_main_IncrementalSf'.
Program terminated with signal SIGFPE, Arithmetic exception.
#0  0x000055dc1f18c7e6 in Eigen::internal::gebp_kernel<double, double, long, Eigen::internal::blas_data_mapper<double, long, 0, 0>, 12, 4, false, false>::operator() (this=0x7f2af88ccf0c, res=..., blockA=0x7f2af88cd340, blockB=0x7f2af88cd3a0, rows=3, depth=0, cols=3, alpha=-1, strideA=0, strideB=0, offsetA=0, offsetB=0)
    at /home/yuyabu/3d/src/openMVG/src/third_party/eigen/Eigen/src/Core/products/GeneralBlockPanelKernel.h:926
926       const Index actual_panel_rows = (3*LhsProgress) * std::max<Index>(1,( (l1 - sizeof(ResScalar)*mr*nr - depth*nr*sizeof(RhsScalar)) / (depth * sizeof(LhsScalar) * 3*LhsProgress) ));
[Current thread is 1 (Thread 0x7f2af88ce700 (LWP 58245))]
(gdb) 

backtraceを取って該当の処理がどこから呼ばれたのか?ということもある程度わかります。

(gdb) bt
#0  0x000055dc1f18c7e6 in Eigen::internal::gebp_kernel<double, double, long, Eigen::internal::blas_data_mapper<double, long, 0, 0>, 12, 4, false, false>::operator() (this=0x7f2af88ccf0c, res=..., blockA=0x7f2af88cd340, blockB=0x7f2af88cd3a0, rows=3, depth=0, cols=3, alpha=-1, strideA=0, strideB=0, offsetA=0, offsetB=0)
    at /home/yuyabu/3d/src/openMVG/src/third_party/eigen/Eigen/src/Core/products/GeneralBlockPanelKernel.h:926
#1  0x000055dc1f2ef74a in Eigen::internal::triangular_solve_matrix<double, long, 2, 2, false, 1, 0>::run (size=3, otherSize=3, _tri=0x7f2af88cdb30, triStride=3, _other=0x7f2af88cdd00, otherStride=3, blocking=...) at /home/yuyabu/3d/src/openMVG/src/third_party/eigen/Eigen/src/Core/products/TriangularSolverMatrix.h:324
#2  0x000055dc1f3214ef in Eigen::internal::triangular_solve_matrix<double, long, 1, 1, false, 0, 1>::run (size=3, cols=3, tri=0x7f2af88cdb30, triStride=3, _other=0x7f2af88cdd00, otherStride=3, blocking=...) at /home/yuyabu/3d/src/openMVG/src/third_party/eigen/Eigen/src/Core/products/TriangularSolverMatrix.h:32
#3  0x000055dc1f36ef5a in Eigen::internal::triangular_solver_selector<Eigen::Transpose<Eigen::Matrix<double, 3, 3, 1, 3, 3> const> const, Eigen::Matrix<double, 3, 3, 1, 3, 3>, 1, 1, 0, -1>::run (lhs=..., rhs=...) at /home/yuyabu/3d/src/openMVG/src/third_party/eigen/Eigen/src/Core/SolveTriangular.h:102
#4  0x000055dc1f36cf13 in Eigen::TriangularViewImpl<Eigen::Transpose<Eigen::Matrix<double, 3, 3, 1, 3, 3> const> const, 1u, Eigen::Dense>::solveInPlace<1, Eigen::Matrix<double, 3, 3, 1, 3, 3> > (this=0x7f2af88cd4e0, _other=...) at /home/yuyabu/3d/src/openMVG/src/third_party/eigen/Eigen/src/Core/SolveTriangular.h:179
#5  0x000055dc1f36ad71 in Eigen::TriangularViewImpl<Eigen::Transpose<Eigen::Matrix<double, 3, 3, 1, 3, 3> const> const, 1u, Eigen::Dense>::solveInPlace<Eigen::Matrix<double, 3, 3, 1, 3, 3> > (this=0x7f2af88cd4e0, other=...) at /home/yuyabu/3d/src/openMVG/src/third_party/eigen/Eigen/src/Core/TriangularMatrix.h:511
#6  0x000055dc1f368157 in Eigen::LLT<Eigen::Matrix<double, 3, 3, 1, 3, 3>, 2>::solveInPlace<Eigen::Matrix<double, 3, 3, 1, 3, 3> > (this=0x7f2af88cdb30, bAndX=...) at /home/yuyabu/3d/src/openMVG/src/third_party/eigen/Eigen/src/Cholesky/LLT.h:496
#7  0x000055dc1f366674 in Eigen::LLT<Eigen::Matrix<double, 3, 3, 1, 3, 3>, 2>::_solve_impl<Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<double>, Eigen::Matrix<double, -1, -1, 1, -1, -1> >, Eigen::Matrix<double, 3, 3, 1, 3, 3> > (this=0x7f2af88cdb30, rhs=..., dst=...) at /home/yuyabu/3d/src/openMVG/src/third_party/eigen/Eigen/src/Cholesky/LLT.h:476
#8  0x000055dc1f3653de in Eigen::internal::Assignment<Eigen::Matrix<double, 3, 3, 1, 3, 3>, Eigen::Solve<Eigen::LLT<Eigen::Matrix<double, 3, 3, 1, 3, 3>, 2>, Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<double>, Eigen::Matrix<double, -1, -1, 1, -1, -1> > >, Eigen::internal::assign_op<double, double>, Eigen::internal::Dense2Dense, void>::run (dst=..., src=...)
    at /home/yuyabu/3d/src/openMVG/src/third_party/eigen/Eigen/src/Core/Solve.h:147
#9  0x000055dc1f364a1d in Eigen::internal::call_assignment_no_alias<Eigen::Matrix<double, 3, 3, 1, 3, 3>, Eigen::Solve<Eigen::LLT<Eigen::Matrix<double, 3, 3, 1, 3, 3>, 2>, Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<double>, Eigen::Matrix<double, -1, -1, 1, -1, -1> > >, Eigen::internal::assign_op<double, double> > (dst=..., src=..., func=...)
    at /home/yuyabu/3d/src/openMVG/src/third_party/eigen/Eigen/src/Core/AssignEvaluator.h:836
#10 0x000055dc1f363a90 in Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 3, 1, 3, 3> >::_set_noalias<Eigen::Solve<Eigen::LLT<Eigen::Matrix<double, 3, 3, 1, 3, 3>, 2>, Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<double>, Eigen::Matrix<double, -1, -1, 1, -1, -1> > > > (this=0x7f2af88cdd00, other=...)
    at /home/yuyabu/3d/src/openMVG/src/third_party/eigen/Eigen/src/Core/PlainObjectBase.h:728
#11 0x000055dc1f362cbd in Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 3, 1, 3, 3> >::PlainObjectBase<Eigen::Solve<Eigen::LLT<Eigen::Matrix<double, 3, 3, 1, 3, 3>, 2>, Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<double>, Eigen::Matrix<double, -1, -1, 1, -1, -1> > > > (this=0x7f2af88cdd00, other=...)
    at /home/yuyabu/3d/src/openMVG/src/third_party/eigen/Eigen/src/Core/PlainObjectBase.h:537
#12 0x000055dc1f361f70 in Eigen::Matrix<double, 3, 3, 1, 3, 3>::Matrix<Eigen::Solve<Eigen::LLT<Eigen::Matrix<double, 3, 3, 1, 3, 3>, 2>, Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<double>, Eigen::Matrix<double, -1, -1, 1, -1, -1> > > > (this=0x7f2af88cdd00, other=...) at /home/yuyabu/3d/src/openMVG/src/third_party/eigen/Eigen/src/Core/Matrix.h:379
#13 0x000055dc1f360df1 in ceres::internal::InvertPSDMatrix<3> (assume_full_rank=true, m=...) at /home/yuyabu/3d/src/openMVG/src/third_party/ceres-solver/internal/ceres/invert_psd_matrix.h:60
#14 0x000055dc1f389aaf in ceres::internal::SchurEliminator<2, 3, 6>::Eliminate (this=0x7f2af88cdcb0, A=0x7f2af88cdd60, b=0x55dc208c71f0, D=0x55dc20595f50, lhs=0x7f2af88cdb40, 
    rhs=0x55dc1f38b360 <ceres::internal::SchurEliminator<2, 3, 6>::ChunkDiagonalBlockAndGradient(ceres::internal::SchurEliminator<2, 3, 6>::Chunk const&, ceres::internal::BlockSparseMatrix const*, double const*, int, Eigen::Matrix<double, 3, 3, 1, 3, 3>*, double*, double*, ceres::internal::BlockRandomAccessMatrix*)+552>)
    at /home/yuyabu/3d/src/openMVG/src/third_party/ceres-solver/internal/ceres/schur_eliminator_impl.h:273

参考: qiita.com

なおデバッグビルドしたバイナリがなくても-cオプションでcorefileだけでgdbを起動できます。

$man gdb
...(略)
OPTIONS
...(略)
       -core=file
       -c file
           Use file file as a core dump to examine.

ただし関数名などがわからないのでアドレスみたらわかるマンじゃないときついと思います。

$ gdb -c core
・・・(略)
[New LWP 58268]
Core was generated by `/home/yuyabu/3d/build/openMVG/Linux-x86_64-DEBUG/openMVG_main_IncrementalSf'.
Program terminated with signal SIGFPE, Arithmetic exception.
#0  0x000055dc1f18c7e6 in ?? ()
[Current thread is 1 (LWP 58245)]