browser() debug statement R - debugging

I have an R script where I have inserted the following code:
options(Debug=TRUE)
#SOME MORE CODE
browser(expr = isTRUE(getOption("Debug")))
#SOME MORE CODE
After the debugger starts, I would like it to proceed to the next line so I type n. However, this does not proceed to the next line but rather seems to continue.
How do I step through the remainder of my code after a browser() statement?
Thanks

To set a point within a function at which to begin debugging, you'll likely want to use trace().
Let's say you have a function myFun and want to begin debugging it right before its call to plot():
myFun <- function() {
x <-
8:1
y <-
1:8
plot(y~x)
lines(y~x)
text(x,y, letters[1:8], pos=3)
}
To construct the call to trace, you will need to know at which step in myFun the call to plot() occurs. To determine that, use the construct as.list(body(myFun)):
as.list(body(myFun))
# [[1]]
# `{`
#
# [[2]]
# x <- 8:1
#
# [[3]]
# y <- 1:8
#
# [[4]]
# plot(y ~ x)
#
# ... More ...
After noting that the call to plot occurs in step 4, you can use trace() to tell R that you'd like to enter a browser right before step 4 every time myFun is called:
trace(myFun, browser, 4)
# TRY IT OUT
# (Once in the browser, type "n" and press Enter to step through the code.)
myFun()
Finally, when you're done debugging the function, turn the trace off with a call to untrace(myFun).
EDIT: The strategy for setting breakpoints for sourced-in scripts is similar. Again, you don't actually insert code into the script. Instead use findLineNum() and setBreakPoint().
Let's say that the function myFun() described above is defined in the text file "myScript.R", which has five blank lines before the function definitions. To insert the breakpoint right before the call to plot:
source("myScript.R") # Must source() once before using findLineNum
# or setBreakPoint
findLineNum("myScript.R#10") # I see that I missed the step by one line
setBreakpoint("myScript.R#11") # Insert the breakpoint at the line that calls
# plot()
myFun() # Test that breakpoint was properly inserted
# (Again, use "n" and Enter to step through code)

browser() is generally for use when running in interactive mode and used in a sub function because if you have it inline in a script and source the whole thing in it will simply execute the next line against the browser prompt when it is called.
E.g. assuming the script:
options(Debug=TRUE)
browser(expr = isTRUE(getOption("Debug")))
b <- 1
b <- 2
b <- 3
It would execute like this:
R> options(Debug=TRUE)
R> browser(expr = isTRUE(getOption("Debug")))
Called from: top level
Browse[1]> b <- 1
Browse[1]> b <- 2
Browse[1]> b <- 3
If you were to run the script step by step and then call a function as so then it's use makes more sense:
R> options(Debug=TRUE)
R> a <- function() {
browser(expr = isTRUE(getOption("Debug")))
b <- 1
b <- 2
b <- 3
return(b)
}
R> e <- a()
Called from: a()
Browse[1]> n
debug at #5: b <- 1
Browse[2]> # ENTER
debug at #6: b <- 2
Browse[2]> b
[1] 1
Browse[2]> # ENTER
debug at #7: b <- 3
Browse[2]> b
[1] 2
Browse[2]> # ENTER
debug at #8: return(b)
Browse[2]> b
[1] 3
Browse[2]> # ENTER
[1] 3
R>

Related

Julia - Broken If statement in while loop?

I am currently trying to constantly check a condition inside an infinite while loop. I am breaking out of the loop with a few conditionals. However, the while loop is immediately breaking and a debugging println() shows that the code is inside of the first if() statement. Hoover, the preceding line was never run and the if statement needs that information (polar) to compute. I only get an error when trying to call polar later in the program and it does not exist. It is as if that line has been entirely skipped.
Here is the while loop in question:
prevSize = 0
sec = 0
n = 5
while true # wait unit the polar file is done changing
polar = readdlm(polarPath,Float64,skipstart = 12)
if polar[end,1] > aEnd - aStep
println("Done writing polar file")
break #File is fully loaded
else #check every n seconds for stable file size
sleep(1)
global sec += 1
if prevSize == filesize(polarPath) && sec == n
println("Polar file could not converge for all AoA")
break # after n seconds if filesize is constant then use current polar
elseif sec >= n
global sec = 0 # reset sec every n seconds
end
global prevSize = filesize(polarPath)
end
end
The program prints out "Done writing polar file" which means that it used the first break. However, polar was never initialized as a variable and separately calling polar[end,1] > aEnd - aStep gives the expected error of no variable called polar. So my question is how can the code have skipped over the line defining polar and then evaluated an if statement that it does not have the information for?
Here is a simple example of how scoping rules work when using a while loop.
First example, using while inside main:
julia> outvar = 5
5
julia> invar = 5
5
julia> while true
global outvar
invar = outvar
outvar += 1
if outvar > 10
break
end
end
julia> outvar
11
julia> invar
5
So I defined both outvar and invar outside of the while loop, accessed the outvar variable outside the scope while by calling global outvar so the loop works and it does update outvar. But our invar variable is still set to 5, as the variable invar inside the while loop is not connected to the outside the while loop - it lives in its own tiny universe.
An easy way to fix this is to create a function:
function add_nums(outvar)
invar = outvar
while true
invar = outvar
outvar += 1
if outvar > 10
break
end
end
return invar
end
This takes an outvar, defines invar outside the while loop so that you can add additional logic here if you wanted to and the executes the loop and returns your new invar.
Once you have this function you can achieve the goal of the original while loop easily:
julia> outvar = 5
5
julia> invar = add_nums(outvar)
10
Even better, your outvar variable is affected by these function calls:
julia> outvar
5
I hope the above example helps you achieve what you want. You just need to create a function that implements your file loading logic.

How can I factor multiples function that gets their result process by another function?

I would like to factorize this code :
(* This function is applied to the result of functions below *)
let manage_result r s =
match r with
| Error ( `Msg e ) -> Tsdl.Sdl.log s e;exit 1
| Ok a -> a
(* Examples of function I want to factorize, let's call them f_functions, f for factorize *)
let init () =
let flag = Tsdl.Sdl.Init.everything in
let result = Tsdl.Sdl.init flag in
manage_result result "Init error : %s"
let create_window title w h =
let flag = Tsdl.Sdl.Window.windowed in
let result = Tsdl.Sdl.create_window title ~w:w ~h:h flag in
manage_result result "Create window error : %s"
let get_window_surface window =
let result = Tsdl.Sdl.get_window_surface window in
manage_result result "Get window surface error : %s"
As you can see, the two last lines of all of these f_functions are very similar. I would like to make a function that takes as argument a function ( for example, if I wanted to factorize init, the function passed as a parameter would be Tsdl.Sdl.init) and return a function that return the return value of function passed as an argument AND processed through manage_result.
The difficulty is that I don't know how many argument can the f_functions take.
Any other recommendations is appreciated!
Thank you.
A potential solution might be to use the pipe operator rather than naming the intermediary result
let on_error s r = manage_result r s
let create_window title w h =
let flag = Tsdl.Sdl.Window.windowed in
Tsdl.Sdl.create_window title ~w:w ~h:h flag
|> on_error "Create window error : %s"
Going one step further, we could define a custom operator for the error handling
let ( <!> ) = manage_result
which may make your definition lightweight enough
let create_window title w h =
let flag = Tsdl.Sdl.Window.windowed in
Tsdl.Sdl.create_window title ~w:w ~h:h flag
<!> "Create window error : %s"

Can I tell LLDB to remove the active breakpoint?

When LLDB triggers breakpoint X, is there a command that will disable or remove X and then continue?
That's an interesting idea. There's no built in command to do this in lldb but it would be easy to implement as a user-defined command written in Python. SBThread::GetStopReason() will be eStopReasonBreakpoint if that thread stopped because of a breakpoint. SBThread::GetStopReasonDataCount() will return 2 -- indicating that the breakpoint id and location id are available. SBThread::GetStopReasonDataAtIndex(0) will give you the breakpoint ID, SBThread::GetStopReasonDataAtIndex(1) will give you the location ID. (a single user-specified breakpoint may resolve to multiple locations. e.g. an inlined function, or a function name that occurs in multiple libraries in a single program.)
Here's a quick & dirty example of a python command that does this. I put this in ~/lldb where I save my lldb user-defined commands and then in my ~/.lldbinit file I have a line like command script import ~/lldb/disthis.py.
In use, it looks like this:
% lldb a.out
(lldb) target create "a.out"
Current executable set to 'a.out' (x86_64).
(lldb) br s -n main
Breakpoint 1: where = a.out`main + 15 at a.c:4, address = 0x0000000100000f4f
(lldb) r
Process 67487 launched: '/private/tmp/a.out' (x86_64)
Process 67487 stopped
* thread #1: tid = 0x290c51, 0x0000000100000f4f a.out`main + 15 at a.c:4, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
#0: 0x0000000100000f4f a.out`main + 15 at a.c:4
1 #include <stdio.h>
2 int main()
3 {
-> 4 puts ("HI");
5 puts ("HI");
6 }
(lldb) com scr imp ~/lldb/disthis.py
(lldb) disthis
Breakpoint 1.1 disabled.
(lldb) br li
Current breakpoints:
1: name = 'main', locations = 1
1.1: where = a.out`main + 15 at a.c:4, address = 0x0000000100000f4f, unresolved, hit count = 1 Options: disabled
(lldb)
Pretty straightforward.
# import this into lldb with a command like
# command script import disthis.py
import lldb
def disthis(debugger, command, *args):
"""Usage: disthis
Disables the breakpoint the currently selected thread is stopped at."""
target = None
thread = None
if len(args) == 2:
# Old lldb invocation style
result = args[0]
if debugger and debugger.GetSelectedTarget() and debugger.GetSelectedTarget().GetProcess():
target = debugger.GetSelectedTarget()
process = target.GetProcess()
thread = process.GetSelectedThread()
elif len(args) == 3:
# New (2015 & later) lldb invocation style where we're given the execution context
exe_ctx = args[0]
result = args[1]
target = exe_ctx.GetTarget()
thread = exe_ctx.GetThread()
else:
print "Unknown python function invocation from lldb."
return
if thread == None:
print >>result, "error: process is not paused, or has not been started yet."
result.SetStatus (lldb.eReturnStatusFailed)
return
if thread.GetStopReason() != lldb.eStopReasonBreakpoint:
print >>result, "error: not stopped at a breakpoint."
result.SetStatus (lldb.eReturnStatusFailed)
return
if thread.GetStopReasonDataCount() != 2:
print >>result, "error: Unexpected number of StopReasonData returned, expected 2, got %d" % thread.GetStopReasonDataCount()
result.SetStatus (lldb.eReturnStatusFailed)
return
break_num = thread.GetStopReasonDataAtIndex(0)
location_num = thread.GetStopReasonDataAtIndex(1)
if break_num == 0 or location_num == 0:
print >>result, "error: Got invalid breakpoint number or location number"
result.SetStatus (lldb.eReturnStatusFailed)
return
bkpt = target.FindBreakpointByID (break_num)
if location_num > bkpt.GetNumLocations():
print >>result, "error: Invalid location number"
result.SetStatus (lldb.eReturnStatusFailed)
return
bkpt_loc = bkpt.GetLocationAtIndex(location_num - 1)
if bkpt_loc.IsValid() != True:
print >>result, "error: Got invalid BreakpointLocation"
result.SetStatus (lldb.eReturnStatusFailed)
return
bkpt_loc.SetEnabled(False)
print >>result, "Breakpoint %d.%d disabled." % (break_num, location_num)
return
def __lldb_init_module (debugger, dict):
debugger.HandleCommand('command script add -f %s.disthis disthis' % __name__)

Echo Timestamp in R Batch Mode

I'd like to better understand the execution duration of statements within an R script when run in batch mode. Is there a good way to do this?
I had one thought on how I'd love to see this done. When executing in batch made the source is echoed to the specified log file. Is there a way for it to echo a timestamp next to the source code in this log file?
> R CMD BATCH script.R script.Rout
Here is the output that I see today.
> tail -f script.Rout
...
> # features related to the date
> trandateN <- as.integer(trandate)
> dayOfWeek <- as.integer(wday(trandate))
> holiday <- mapply(isHoliday, trandate)
I'd like to see something like...
> tail -f script.Rout
...
2013-06-27 11:18:01 > # features related to the date
2013-06-27 11:18:01 > trandateN <- as.integer(trandate)
2013-06-27 11:18:05 > dayOfWeek <- as.integer(wday(trandate))
2013-06-27 11:19:02 > holiday <- mapply(isHoliday, trandate)
You can use addTaskCallback as follows to create a log of each top level execution.
.log <- data.frame(time=character(0), expr=character(0))
.logger <- function(expr, value, ok, visible) { # formals described in ?addTaskCallback
time <- as.character(Sys.time())
expr <- deparse(expr)
.log <<- rbind(.log, data.frame(time, expr))
return(TRUE) # required of task callback functions
}
.save.log <- function() {
if (exists('.logger')) write.csv(.log, 'log.csv')
}
addTaskCallback(.logger)
x <- 1:10
y <- mean(x)
.save.log()
.log
# time expr
# 1 2013-06-27 12:01:45.837 addTaskCallback(.logger)
# 2 2013-06-27 12:01:45.866 x <- 1:10
# 3 2013-06-27 12:01:45.876 y <- mean(x)
# 4 2013-06-27 12:01:45.900 .save.log()
Of course instead of committing the cardinal sin of growing a data.frame row-wise, as I have here, you could just leave a connection open and write directly to file, closing the connection with on.exit.
And if you want to be tidy about it, you can pack the logging setup into a function pretty nicely.
.log <- function() {
.logger <<- local({
log <- data.frame(time=character(0), expr=character(0))
function(expr, value, ok, visible) {
time <- as.character(Sys.time())
expr <- deparse(expr)
log <<- rbind(log, data.frame(time, expr))
return(TRUE)
}
})
invisible(addTaskCallback(.logger))
}
.save.log <- function() {
if (exists('.logger'))
write.csv(environment(.logger)$log, 'log.csv')
}
.log()
x <- 1:10
y <- mean(x)
.save.log()
See ?Sys.time. It returns a POSIXct datetime, which you'll need to format when outputting to a log file.
cat(format(Sys.time()), " is the current time\n")

Using gdb, display multiple vars in one line?

How can I ask to display multiple vars in one line? So I want to get output like:
30 if(s[i] != '\0')
5: s[i] = 101 'e'
4: exp = 14
3: val = 123.45
2: sign = 1
1: i = 6
I've been typing in disp s[i] ENTER disp exp ENTER (etc, etc) and I just know there's got to be a better way to do this in one line of typing.
To establish multiple active "variable displays" without re-typing each of display i, display s[i], etc. every time you restart GDB, use a GDB "canned command sequence".
For example, add this to your ~/.gdbinit:
define disp_vars
disp i
disp sign
disp val
disp exp
disp s[i]
end
Now you can add all the displays at once by typing disp_vars at the GDB prompt.
Employed Russian gave the correct solution but for those that want see it used in an example see below. If you're not sure if you want to commit to putting the .gdbinit in your home directory, you can also put it in the directory you're executing the program from to experiment.
$ gcc -g atof_ex4.2.c
$ gdb ./a.out
(gdb) b 30
Breakpoint 1 at 0x1907: file atof_ex4.2.c, line 30.
(gdb) h user-defined
List of commands:
disp_vars -- User-defined
(gdb) disp_vars #this will enable the user defined canned sequence (but I haven't done run yet! So I'll this actually doesn't work yet.)
No symbol "i" in current context.
(gdb) r
Starting program: a.out
Breakpoint 1, atof (s=0xbffff028 "123.45e-6") at atof_ex4.2.c:30
30 if(s[i] != '\0')
(gdb) s # No disp_vars output yet because I have to do it AFTER 'run' command
32 if(s[i] == 'e' || s[i] == 'E')
(gdb) disp_vars # Now it will work ;)
(gdb) s
35 sign = (s[i] == '-') ? -1 : 1;
5: s[i] = 45 '-'
4: exp = 14
3: val = 123.45
2: sign = 1
1: i = 7
Of course 'r' is for run, 's' is for step, 'b' is for break, etc. I've also omitted some output. Notice that I had to enter the 'disp_vars' command again after 'run'. Thanks Employed Russian.

Resources