gdb with R
Earlier this week I figured out how to turn on assertion errors for debugging Eigen C++ code in an R package, which results in crashes with incomprehensible messages like
R: /home/tdhock/R/i686-pc-linux-gnu-library/3.5/RcppEigen/include/Eigen/src/Core/CwiseBinaryOp.h:110: Eigen::CwiseBinaryOp<BinaryOp, Lhs, Rhs>::CwiseBinaryOp(const Lhs&, const Rhs&, const BinaryOp&) [with BinaryOp = Eigen::internal::scalar_difference_op<double, double>; LhsType = const Eigen::Block<Eigen::Map<Eigen::Matrix<double, -1, -1> >, 1, -1, false>; RhsType = const Eigen::Map<Eigen::Matrix<double, -1, 1> >; Eigen::CwiseBinaryOp<BinaryOp, Lhs, Rhs>::Lhs = Eigen::Block<Eigen::Map<Eigen::Matrix<double, -1, -1> >, 1, -1, false>; Eigen::CwiseBinaryOp<BinaryOp, Lhs, Rhs>::Rhs = Eigen::Map<Eigen::Matrix<double, -1, 1> >]: Assertion `aLhs.rows() == aRhs.rows() && aLhs.cols() == aRhs.cols()' failed.
To get a more informative message I used gdb.
First I tell the compiler to save debugging info via the -g
flag,
added in the src/Makevars file:
PKG_CPPFLAGS=-UNDEBUG -g
Then I use the -d
flag to tell R to start with the gdb debugger,
and the -e
flag to run my test R script:
R -d gdb -e 'source("../tests/testthat/test-knn.R")'
That gives me a gdb command line. run
starts R,
then I get another prompt after R crashes:
> source("../tests/testthat/test-knn.R")
R: ... : Assertion `aLhs.rows() == aRhs.rows() && aLhs.cols() == aRhs.cols()' failed.
Program received signal SIGABRT, Aborted.
0x00007ffff5b31214 in raise ()
from /cvmfs/soft.computecanada.ca/nix/var/nix/profiles/16.09/lib/libc.so.6
(gdb)
bt 10
gives me the 10 highest frames in the stack.
The relevant lines (in my code) are:
#6 Predict1toMaxNeighbors (train_inputs_ptr=0x2,
train_label_ptr=0x7ffffffe6580, nrow=0, ncol=-1, max_neighbors=0,
test_input_ptr=0x7ffffffe6580, test_prediction_ptr=0xbe1f400)
at knn.cpp:32
#7 0x00007fffe164e5ca in Predict1toMaxNeighbors_interface(double*, double*, int*, int*, int*, double*, double*) ()
from /home/thocking/R/x86_64-pc-linux-gnu-library/3.5/nearestNeighbors/libs/nearestNeighbors.so
From frame #6 we see that the assertion was raised on line 32 of knn.cpp.
f 6
shows the line of code responsible:
(gdb) f 6
#6 Predict1toMaxNeighbors (train_inputs_ptr=0x2,
train_label_ptr=0x7ffffffe6580, nrow=0, ncol=-1, max_neighbors=0,
test_input_ptr=0x7ffffffe6580, test_prediction_ptr=0xbe1f400)
at knn.cpp:32
32 distance_vec(i) = (train_inputs_mat.row(i)-test_input_vec).norm();
(gdb)
Then normally p
can be used to print the values
of the variables in that frame,
but it did not work for me:
(gdb) p i
$1 = <optimized out>
(gdb) p test_input_vec
$2 = <optimized out>
Anyway, having the line number where the assertion happened
is extremely useful. Once I know the line number,
I can use std::cout
to print values of variables on that line,
after recompiling.