mtrace sets or clears debugging mode for a function;
mtrace.off clears debugging mode for all functions;
check.for.tracees shows which functions are in debugging mode.
1 2 3 4
quoted or unquoted function name, or unquoted reference to function in package (via
TRUE to turn tracing on, FALSE to turn it off
(rarely used) if your function name is stored in a character object
where to start looking for
(character or integer) position in search path
don't set this parameter! It's only for use by other functions
if TRUE, this will return a list of the environments where the function has been replaced by the
mtrace(myfun) modifies the body code of
myfun, and also stores debugging information about
tracees$myfun. Next time the function is invoked, the modified debug-ready version will be called instead of the orginal.
mtrace does not modify source code (or other) attributes, so
myfun will "look" exactly the same afterwards.
myfun to normal.
mtrace.off unmtraces all mtraced functions (see below for exceptions).
mtrace modifies function bodies (possibly in several places, if namespaced packages are involved), calling
save while functions are still
mtraced is probably not a good idea– if the saved image is reloaded in a new R session, the debugger won't know how to handle the previously
mtraced functions, and an error message will be given if they are invoked. The
Save.pos functions in package mvbutils will get round this without your having to manually untrace and retrace functions.
If you do see a "maybe saved before being un-mtraced?" error message when
myfun is invoked, all is not lost; you can restore
myfun to health via
mtrace(myfun,F), or put it properly into debugging mode via
mtrace.off won't work in such cases, because
myfun isn't included in
check.for.tracees checks for functions which have been
mtraced, but only in one directory. By contrast,
names(tracees) will return all functions that are currently known to be
mtraced. However, unlike
names(tracees) won't show functions that were saved during a previous R session in an
mtrace.off will try to untrace all functions. Specifically, it deals with those returned by
names( tracees) and/or
check.for.tracees( 1). It doesn't currently deal with methods of reference-class and S4-class objects, for which you'll need to call
mtrace(..., tracing=FALSE) manually.
mtrace puts a breakpoint (see
bp) at line 1, but clears all other breakpoints.
mtrace can handle
mlocal functions, but not (yet)
do.in.envir functions– the latter appear as monolithic statements in the code window. See package mvbutils for more details.
If you use
fixr to edit functions,
mtrace will automatically be re-applied when an updated function file is sourced back in. Otherwise, you'll need to call
mtrace manually after updating a function.
mtrace by default looks for a function in the following places: first in the frame stack, then in the search path, then in all namespaces, then in all S3 methods tables. If several copies of a function are found, all will get modified (mtraced) to the same code; ditto when unmtracing.
For functions that live somewhere unusual, you'll need to set the
from argument. One case is for functions that live inside a list, such as family-functions like
poisson for GLMs. Another case is as follows. Suppose there is a function
f which first defines functions
h, then calls
g. Now suppose you have
f and then
g from inside
f, and that
g is currently running. If you now want to
mtrace(h), the problem is that
h is not visible from the frame of
g. To tell
mtrace where to find
mtrace( h, from=sys.parent()). [You can also replace
sys.parent() with the absolute frame number of
f has been
mtraced and its code window is visible.]
mtrace will then look through the enclosing environments of
from until it finds a definition of
myfun has been defined in a namespaced package, then there may be several copies of
myfun in the system, different ones being used at different times.
mtrace will change them all; see
fun.locator if you really want to know more.
mtrace(bar) is called while function
foo is being debugged (
mtrace(foo) having previously been called), and
bar has been redefined within
foo or a parent environment of
foo, then only the redefined copy of
bar will be
S4 methods can be
mtraced, but like much about S4 it's clunky; see
package?debug. Reference class methods can be
mtraced easily after an object has been instantiated. You might call this "object-level" mtracing, because it only works for one object of each class at a time. To
mtrace e.g. the
edit method in the example for "?ReferenceClasses", just do:
You can also do "class-level" mtracing, so that all subsequently-created objects of that class will use the
mtraced version. Just do this:
1 2 3
In the "class-level" case,
xx will still have an
mtraced version of
edit even after the
mtrace( from=mEditor..., FALSE). You'll need to use the "object-level" technique to clear it.
As of April 2011, methods are only set up inside a ref-class object when they are first accessed, not when the object is created.
fun.locator) works round this.
Probably many; but the main one I'm aware of, is the inability to have
mtrace on simultaneously for two functions that have the same name but that have different bodies and live in different places. In theory, the solution is for me to incorporate "location" into the function-level debug info in
mtracees, but I've not been able to figure out a good general-purpose way to do so. If this describes your particular debugging hell, you certainly have my sympathy...
mtrace by default returns an invisible copy of the modified function body. If you set
return.envs=TRUE, it will instead return a list of the environments in which the function has been modified. This is only intended for "internal use".
check.for.tracees returns a character vector of function names.
1 2 3 4 5 6 7 8 9 10 11
## Not run: mtrace(glm) # turns tracing on names( tracees) # "glm" check.for.tracees( "package:base") # "glm" glm(stupid.args) # voila le debugger qqq() # back to command prompt mtrace( glm, FALSE) mtrace.off() # turns it off for all functions mtrace( debug:::setup.debug.admin) # woe betide ye ## End(Not run)