On 25 March 2010 23:18, Andrei Stebakov lispercat@gmail.com wrote:
I am trying to debug a web app (based on hunchentoot and weblocks). Let's say I have a function
(defun test-func(a) (let ((b 1) (c 2)) (break)))
I call this (test-func 0) from (defun weblocks-dispatcher (request) ....) When I hit break, am I supposed to see a, b and c as local variables in the frame? All I can see is the request parameter of weblocks-dispatcher and not even the frame for test-func, what I am missing?
It all comes down to: "Use a higher debug level."
Either use DEBUG 2 -- or 3, if you really want the maximum info, but 3 has both notable runtime and compile-time costs in SBCL.
In addition to having a low debug-level, you're not seeing the frame in your example because BREAK has been tail-called. Changing the code to
(defun test-func(a) (let ((b 1) (c 2)) (break) t))
gets rid of the tail call, so you see the frame:
0: (BREAK "break") 1: (TEST-FUNC #<unavailable argument>) Locals: SB-DEBUG::ARG-0 = :<NOT-AVAILABLE> 2: (SB-INT:SIMPLE-EVAL-IN-LEXENV (TEST-FUNC 1) #<NULL-LEXENV>)
Also, since the values are never used the variables are optimized away. Changing the code to
(defun test-func (a) (let ((b (+ a 1)) (c (+ a 2))) (break) (+ a b c)))
gets you
1: (TEST-FUNC 1) Locals: SB-DEBUG::ARG-0 = 1 2: (SB-INT:SIMPLE-EVAL-IN-LEXENV (TEST-FUNC 1) #<NULL-LEXENV>)
-- you're still missing the name of the argument, and B and C have been optimized away as they are used only once. The code has been compiled as if you had written (+ a (+ a 1) (+ a 2)) instead of (+ a b c).
Debug 2 is enough to sort that out:
(defun test-func (a) (declare (optimize (debug 2))) (let ((b (+ a 1)) (c (+ a 2))) (break) (+ a b c)))
0: (BREAK "break") 1: (TEST-FUNC 1) Locals: A = 1 B = 2 C = 3 2: (SB-INT:SIMPLE-EVAL-IN-LEXENV (TEST-FUNC 1) #<NULL-LEXENV>)
...but you see, already the higher debug level is starting to cost in the form of elided optimizations -- but for many applications DEBUG 2 is a nice halfway house.
Cheers,
-- Nikodemus