How to debug (line-by-line) Rcpp generated code in Windows?

后端 未结 2 1066
清歌不尽
清歌不尽 2021-01-05 11:25

I am trying to debug Rcpp compiled code at run-time. I have been trying to get this to work unsuccessfully, for a very long time. A very similar question was as

相关标签:
2条回答
  • 2021-01-05 12:02

    It can be done with Visual Studio Code, since it can handle both R and C++. This allows you to step through your Rcpp code one line at a time in a GUI environment.

    See this demo to get started.

    0 讨论(0)
  • 2021-01-05 12:06

    The usual approach R -d gdb, which I also suggested in my original answer below, does not work on Windows:

    --debugger=name
    -d name

    (UNIX only) Run R through debugger name. For most debuggers (the exceptions are valgrind and recent versions of gdb), further command line options are disregarded, and should instead be given when starting the R executable from inside the debugger.

    https://cran.r-project.org/doc/manuals/r-release/R-intro.html#Invoking-R-from-the-command-line

    Alternative:

    1. Start R in debugger: gdb.exe Rgui.exe
    2. Set break point: break TimesTwo2
    3. Run R: run
    4. Source file: Rcpp::sourceCpp("debug.cpp")
    5. Use next, print, display to step through the code.

    An alternative to step 1. would be to start R, get the PID with Sys.getpid(), attach debugger with gdb -p <pid>. You will than have to use continue instead of run.


    I don't have a Windows machine right now, so the following was done on Linux. I hope it is transferable, though. Let's start with a simple cpp file (debug.cpp in my case) that contains your code:

    #include <Rcpp.h>
    using Rcpp::NumericVector;
    
    // [[Rcpp::export]]
    NumericVector timesTwo2(NumericVector x) {
      for(int ii = 0; ii <= x.size(); ii++)
      {
        x.at(ii) = x.at(ii) * 2;
      }
      return x;
    }
    
    /*** R
    data = c(1:10)
    data
    timesTwo2(data)
    */
    

    I can reproduce the error by calling R on the command line:

    $ R -e "Rcpp::sourceCpp('debug.cpp')"
    
    R version 3.5.1 (2018-07-02) -- "Feather Spray"
    [...]
    
    > Rcpp::sourceCpp('debug.cpp')
    
    > data = c(1:10)
    
    > data
     [1]  1  2  3  4  5  6  7  8  9 10
    
    > timesTwo2(data)
    Error in timesTwo2(data) : Index out of bounds: [index=10; extent=10].
    Calls: <Anonymous> ... source -> withVisible -> eval -> eval -> timesTwo2 -> .Call
    Execution halted
    

    Next we can start R with gdb as debugger (c.f. Writing R Extensions as Dirk said):

    $ R -d gdb -e "Rcpp::sourceCpp('debug.cpp')"
    GNU gdb (Debian 8.2-1) 8.2
    [...]
    (gdb) break timesTwo2
    Function "timesTwo2" not defined.
    Make breakpoint pending on future shared library load? (y or [n]) y
    Breakpoint 1 (timesTwo2) pending.
    (gdb) run
    [...]
    > Rcpp::sourceCpp('debug.cpp')
    [Thread 0xb40d3b40 (LWP 31793) exited]
    [Detaching after fork from child process 31795]
    
    > data = c(1:10)
    
    > data
     [1]  1  2  3  4  5  6  7  8  9 10
    
    > timesTwo2(data)
    
    Thread 1 "R" hit Breakpoint 1, 0xb34f3310 in timesTwo2(Rcpp::Vector<14, Rcpp::PreserveStorage>)@plt ()
       from /tmp/RtmphgrjLg/sourceCpp-i686-pc-linux-gnu-1.0.0/sourcecpp_7c2d7f56744b/sourceCpp_2.so
    (gdb)
    

    At this point you can single step through the program using next (or just n) and output variables using print (or just p). A useful command is also display:

    Thread 1 "R" hit Breakpoint 1, timesTwo2 (x=...) at debug.cpp:5
    5   NumericVector timesTwo2(NumericVector x) {
    (gdb) n
    6     for(int ii = 0; ii <= x.size(); ii++)
    (gdb) n
    8       x.at(ii) = x.at(ii) * 2;
    (gdb) display ii
    2: ii = 0
    (gdb) n
    8       x.at(ii) = x.at(ii) * 2;
    2: ii = 0
    
    [...]
    
    2: ii = 9
    (gdb) 
    46          inline proxy ref(R_xlen_t i) { return start[i] ; }
    2: ii = 9
    (gdb) 
    6     for(int ii = 0; ii <= x.size(); ii++)
    2: ii = 10
    (gdb) 
    8       x.at(ii) = x.at(ii) * 2;
    2: ii = 10
    (gdb) 
    Error in timesTwo2(data) : Index out of bounds: [index=10; extent=10].
    Calls: <Anonymous> ... source -> withVisible -> eval -> eval -> timesTwo2 -> .Call
    Execution halted
    [Detaching after fork from child process 32698]
    [Inferior 1 (process 32654) exited with code 01]
    

    BTW, I used the following compile flags:

    $ R CMD config CXXFLAGS
    -g -O2 -Wall -pedantic -fstack-protector-strong -D_FORTIFY_SOURCE=2
    

    You might want to switch to -O0.

    0 讨论(0)
提交回复
热议问题