DOC HOME SITE MAP MAN PAGES GNU INFO SEARCH PRINT BOOK
 
Using the command line interface of debug

Session 4: who stepped on my pointer?

  1. Fix the bug in Session 3 by changing line 52 to
       node->left = defn;
    

  2. Recompile macros:
       $ cc -g -o macros main.c macro.c
       main.c:
       macro.c:
    
    You are now ready to test out the more complicated case: macros with parameters.

  3. Run macros with input from test2:
       $ macros <test2
    
    The debugger displays the following:
       a and
    
    Another error is found. Since the program seems to work correctly for parameterless macros, the bug is probably in either getargs, which collects the macro's actual arguments, or in expand where it does the substitution.

  4. Type debug to start the debugger. Investigate getargs:
       debug> create macros
    
    The debugger displays the following:
       New program macros (process p1) created
       HALTED p1 [main in main.c]
       308:            for (i = 1; i < argc; ++i)
    
    Type in the following:
       debug> stop getargs
    
    The debugger displays the following:
       EVENT [1] assigned
    
    Since you did not redirect macros' input, this time when you let it run the program will wait for you to type in something.


    NOTE: debug will not tell you when your program is waiting for input; debug does not know that the program is reading from the terminal instead of from a file.

  5. Run the program:
       debug> run
    

  6. The program is waiting for input. Type in the following:
       define(a1,$1 and $2)
       

    a1(a,b)

    The debugger displays the following:
       STOP EVENT TRIGGERED: getargs  in p1 [getargs in main.c]
       234:            struct arglist        *head = 0;
    
    If you look at the listing of main.c, you will see that the primary action in getargs is looping on a list of input tokens.

  7. Stop at the top of the while loop and check out the list of tokens:
       debug> stop 250
    
    The debugger displays the following:
       EVENT [2] assigned
    
    Run the program:
       debug> run
    
    The debugger displays the following:
       STOP EVENT TRIGGERED: 250  in p1 [getargs in main.c]
       250:                    if (tok->type == COMMA && !parens)
    
    Print out the first token:
       debug> print *tok
    
    The debugger displays the following:
       {
               string="a"
               type=WORD (or 0)
               next=0x804ac90
       }
    
    Print out the second token in the list:
       debug> print *tok->next
    
    The debugger displays the following:
       {
               string=NULL
               type=COMMA (or 4)
               next=0x804aca0
       }
    
    The first and second tokens in the list are just what you expected, so let it continue:
       debug> run
    
    The debugger displays the following:
       a and
    

  8. Hit <Ctrl-D> The debugger displays the following:
       Process p1 has exited
       No more processes.
    
    What happened to the rest of the list of tokens? It should have stopped at the top of the loop on each token.

  9. Run it again, as far as getargs:
       debug> create macros <test2
    
    The debugger displays the following:
       New program macros (process p2) created
       HALTED p2 [main in main.c]
       308:            for (i = 1; i < argc; ++i)
    
    Run the program:
       debug> run
    
    The debugger displays the following:
       STOP EVENT TRIGGERED: getargs  in p2 [getargs in main.c]
       234:            struct arglist        *head = 0;P
    

  10. This time you will have to look more carefully at what is going on in the while loop. Create an event to stop at both the top and the bottom of the loop (before it resets tok) and print the current token:
       debug> delete 2
       debug> b 250||289 print *tok
    


    NOTE: See ``Watchpoints, breakpoints, and general stop expressions''.

    The debugger displays the following:

       EVENT [3] assigned
    

  11. Run the program:
       debug> run
    
    The debugger displays the following:
       STOP EVENT TRIGGERED: 250 || 289  in p2 [getargs in main.c]
       250:                  if (tok->type == COMMA && !parens)
       {
           string="a"
           type=WORD (or 0)
           next=0x804ac90
       }
    

  12. Run the program:
       debug> run
    
    The debugger displays the following:
       STOP EVENT TRIGGERED: 250 || 289  in p2 [getargs in main.c]
       289:                    *inlist = tok->next;
       {
           string="a"
           type=WORD (or 0)
           next=0x0
       }
    
    It looks like the token's next pointer got stepped on somewhere; that would explain why it left the loop after only one token.

  13. Back up and run it again to see where the next pointer was changed:
       debug> create
    
    The debugger displays the following:
       p2 killed
       macros <test2
       New program macros (process p3) created
       HALTED p3 [main in main.c]
       308:            for (i = 1; i < argc; ++i)
    

  14. Run the program:
       debug> run
    
    The debugger displays the following:
       STOP EVENT TRIGGERED: getargs  in p3 [getargs in main.c]
       226:            struct arglist        *head = 0;
    

  15. Run the program again:
       debug> run
    
    The debugger displays the following:
       STOP EVENT TRIGGERED: 250 || 289  in p3 [getargs in main.c]
       242:                  if (tok->type == COMMA && !parens)
       {
           string="a"
           type=WORD (or 0)
           next=0x804ac90
       }
    

  16. Before you let it go through the loop again, set a watchpoint on the token's next pointer:
       debug> stop *tok->next { print *tok }
       EVENT [4] assigned
    

  17. Run the program and it will stop at the first line after tok->next changes:
       debug> run
    
    The debugger displays the following:
       Warning: Stepping p3 to watch stop expression
       STOP EVENT TRIGGERED: *tok->next  in p3 [getargs in main.c]
       289:                    *inlist = tok->next;
       {
           string="a"
           type=WORD (or 0)
           next=0x0
       }
    

  18. Look at the previous lines to see what happened:
       debug> list -c 3 287
    
    The debugger displays the following:
       287:                    argtail = tok;
       288:                    argtail->next = 0;
       289:                    *inlist = tok->next;
    
tok and argtail point to the same space. When argtail->next is set to zero, that also changes tok->next.

Watchpoints, breakpoints, and general stop expressions

Setting a watchpoint tells debug to stop the program when a variable changes value. This is just another form of stop event. There are three types of stop events, each of which has some action that will make the debugger notice the event. When the action occurs, the debugger evaluates the entire stop expression, and if true, stops the process and executes any associated commands. The three types of stop events are:


You can create events of considerable complexity by combining breakpoints, watchpoints, and expressions in one stop expression with the and (&&) and or (||) operators:
   debug> stop foo || *ptr
   ...
   debug> stop getargs && malloc
   ...
   debug> stop 229 && (a > b)
   ...
In the first example, debug will set a breakpoint on the function foo and a watchpoint on ptr; whichever event trigger happens first will make the process stop.

The second example is more interesting. For locations that refer to function names, the expression is true as long as the function is active (until the process returns from that function). Here the debugger will stop the process in malloc only when it is called from the function getargs. This is a handy way to debug a function that is called from several places but shows up a problem in only one area.

For locations that refer to addresses or line numbers, the expression is true only when the process is at that address or the beginning of the line. In the third example, the debugger will stop the process when it reaches line 229 only if a is greater than b.


Next topic: Session 5: why didn't that signal handler work?
Previous topic: Variations on run and step

© 2004 The SCO Group, Inc. All rights reserved.
UnixWare 7 Release 7.1.4 - 27 April 2004