Debugging Techniques
FedoraForum.org - Fedora Support Forums and Community
Page 1 of 3 1 2 3 LastLast
Results 1 to 15 of 33
  1. #1
    Join Date
    Oct 2010
    Location
    Canberra
    Posts
    2,952

    Debugging Techniques

    I thought I might kick off a thread where we can share tips on debugging programs and ask other debugging related questions.

    I have a short list of bug types and their symptoms:
    1. Uninitialised variables: Works first time, crashes the next time the function runs.
    2. Race condition: Works OK sometimes, scrambled at other times.
    3. Memory corruption: Crashes at a consistent point when doing something that is OK of itself. Changing something before the corruption may change the crash point.
    4. Stack overwrite: Crash on return from function.
    5. Confused Ownership: Value of an object changes unexpectedly. (This is a multi-threaded issue.)
    6. Performance bugs: Performance deteriorates rapidly as the size of the data set increases.


    Debugging is a lot like the scientific method.
    First you observe something unexpected.
    Then you collect any other evidence and form a hypothesis about what might be wrong.
    Then you do some experiments to confirm or reject the hypothesis.
    If the hypothesis is rejected then you again look at the evidence and construct a better hypothesis.
    Eventually you have found the cause of the bug.
    Then you need to design a solution that won't introduce more bugs, implement it, and then test it.
    Ideally you will have a test suite to put the program through its paces - this needs to be run to ensure you have not broken something else.
    Finally you might add a new test to the test suite to make sure the bug doesn't reappear and go unnoticed.
    Last edited by ocratato; 19th January 2018 at 01:13 AM.

  2. #2
    Join Date
    Nov 2008
    Posts
    415

    Re: Debugging Techniques

    It's good if you can compare outputs (using xxdiff, for example), of different program
    versions.

    Sometimes it is good to have "independent verification" - process the inputs using an
    interpreted language like awk or rexx (perhaps in a prototype), and then compare outputs
    with the compiled "production" version of the program.

    I've never liked interactive debugging - too much effort, but prefer a batch approach -
    run the program, check the output, put in debugging displays as needed. oorexx, like
    bash, has the nice "trace" feature to display each line of code as it is executed,
    optionally with intermediate values displayed.

  3. #3
    Join Date
    Oct 2010
    Location
    Canberra
    Posts
    2,952

    Re: Debugging Techniques

    Quote Originally Posted by dswaner
    I've never liked interactive debugging - too much effort, but prefer a batch approach -
    run the program, check the output, put in debugging displays as needed. oorexx, like
    bash, has the nice "trace" feature to display each line of code as it is executed,
    optionally with intermediate values displayed.
    I tend to agree. as soon as you have multiple libraries and threads the interactive approach sort of breaks down.
    However, I can imagine having a function doing a lot of maths that isn't working as expected. Stepping through it and looking at the variables would be useful.

    Quote Originally Posted by dswaner
    It's good if you can compare outputs (using xxdiff, for example), of different program
    versions.

    Sometimes it is good to have "independent verification" - process the inputs using an
    interpreted language like awk or rexx (perhaps in a prototype), and then compare outputs
    with the compiled "production" version of the program.
    Yes, the first step in debugging, is to determine that there are bugs that need fixing. (There are always bugs.)

    The first line of defence is to have code that checks its own state and reports issues.

    The next is to have a test harness to put the program through as many corner cases as you can afford.

    I have found that having good logging is very useful for a production system. I have often been able to spot impending problems by regularly examining production logs.

    The final, and worst, is the report from the user that the program failed. Unfortunately sometimes its only the user that can cause the bug to manifest itself. I once had a bug that was only triggered by a very fast typist.

  4. #4
    Join Date
    Feb 2005
    Location
    London, UK
    Posts
    657

    Re: Debugging Techniques

    Quote Originally Posted by dswaner
    I've never liked interactive debugging - too much effort, but prefer a batch approach -
    run the program, check the output, put in debugging displays as needed.
    But what if you have a monitoring program (for example) that runs "green" for a random amount of time in a while(1) loop and then randomly turns red for 1 frame? You know the underlying reason for it being "green" is fine so it must be issue in your code, how can batch help you with that? A "break if status!=green" will freeze you at the odd occurrence and and then you can inspect the state of the program, probably finding that one variable is showing junk due to forgetting to terminate a string in C or some such stupid mistake.

  5. #5
    Join Date
    Nov 2008
    Posts
    415

    Re: Debugging Techniques

    I'm sure you're right - there's a place for interactive debugging, and you give a good example. Debugging the kernel or gnome-shell, for example, is a whole other world to my experience, where I've managed fine without watch points.

  6. #6
    Join Date
    Jun 2005
    Location
    Montreal, Que, Canada
    Posts
    5,223

    Re: Debugging Techniques

    The biggest cause of bugs that occur are due to mis-understanding the documentation. It is always good to confirm that the arguments to a function call, and the results returned are not what you remembered, but correspond to what was documented.
    Leslie in Montreal

    Interesting web sites list
    http://forums.fedoraforum.org/showth...40#post1697840

  7. #7
    Join Date
    Oct 2010
    Location
    Canberra
    Posts
    2,952

    Re: Debugging Techniques

    From the discussion so far I think we can conclude that the best debugging technique will depend on the type of program, the circumstances in which it runs, and the experience of the person doing the debugging.

    So you have a program and its either crashed, failed an assertion, thrown an exception, reported something in a log, failed a test case, or a user has reported an anomaly.

    The next thing is to try and reproduce the problem. If you cannot reproduce the problem its going to be rather difficult to fix and impossible to demonstrate that you have fixed it. For this you will need to set up the conditions that cause the problem: this might be just re-running a test case, or it might involve grabbing a snapshot of a production database. You may need to do some experiments with the data and environment to find what it is that is triggering the problem.

    While it is often the case that once the conditions for the problem are in place it will always occur there are some types of bugs that are a lot less deterministic. When tracking down a race condition I put the test case in a script and run it repeatedly until the error manifests itself.

    Once the problem can be reproduced we can start to try to find the code responsible.

  8. #8
    Join Date
    Oct 2010
    Location
    Canberra
    Posts
    2,952

    Re: Debugging Techniques

    Quote Originally Posted by lsatenstein
    The biggest cause of bugs that occur are due to mis-understanding the documentation. It is always good to confirm that the arguments to a function call, and the results returned are not what you remembered, but correspond to what was documented.
    This usually manifests itself as a failure to check the return value from a function call and ignoring the reported error condition.

  9. #9
    Join Date
    Jun 2005
    Location
    Montreal, Que, Canada
    Posts
    5,223

    Angry Re: Debugging Techniques

    It is usually a beginner lacune or an omission by someone who should not be let near production code. The person who says "I'll do the error checking tomorrow", and tomorrow is another challenge, that takes priority. ... Well, you know the story and the history ...

    I worked in banking, and in manufacturing and with both we had a hierarchy of approvals to sign off on any code change.
    We had names for guys whose code did not pass quality testing.
    Sloppy untrustworthy xxxxxxxxxxxxx
    Last edited by lsatenstein; 11th January 2018 at 06:23 PM.
    Leslie in Montreal

    Interesting web sites list
    http://forums.fedoraforum.org/showth...40#post1697840

  10. #10
    Join Date
    Nov 2008
    Posts
    415

    Re: Debugging Techniques

    If you work with hex data, a vertical hex listing is good:
    Code:
                    1----+----2----+----3----+----4----+----5
       10 TO    50  m.....t|...wo.*d-q..G.....Q.8...|ye.&....
                    6bab717700176126270f4cfeee513aff776a28bcb
                    dff5f04c4aa7f3a4d1467a9b511e8045c951647a0

  11. #11
    Join Date
    Oct 2010
    Location
    Canberra
    Posts
    2,952

    Re: Debugging Techniques

    Once you have a bug, the first step is to isolate the code that is causing the problem.
    For this you can use a debugger and place breaks at strategic points in the code. However, sometimes a debugger may not be available, or is not appropriate for the type of bug.

    One of the first programs I wrote as a professional programmer had an interesting bug - it crashed the compiler. Its hard to use a debugger in this case. After a fair amount of trying out various ideas I eventually decided to try to isolate the problem code by creating a new version of the program and compiling it after adding a few lines at a time. In the end I had two copies of the source code that appeared to be identical, except one compiled fine and the other crashed the compiler.

    While some might have just said, OK now it works, lets just move on, I like to actually understand what the underlying cause is. This way you are less likely to fall into the same trap another time. (Of course bosses don't often understand this.)

    On closer inspection it turned out that the "error" was a blank line at the end of the file. Apparently once the compiler had read the program's termination symbol it failed if it was not at the end of file.

  12. #12
    Join Date
    Oct 2010
    Location
    Canberra
    Posts
    2,952

    Re: Debugging Techniques

    A method to use when a debugger isn't convenient is to put print statements in the code to localise the problem.
    Sometimes the results can be a bit perplexing:
    Code:
    printf("got here %d\n", __LINE__);
    a = b/c;
    printf("got here %d\n", __LINE__);
    The program froze during a simple divide. A quick check showed that the numbers being divided were as expected. The CPU just went into a very tight infinite loop during the division operation.

    Fortunately my supervisor at the time was a bit of an expert on the CPU - a RISC processor - and was able to deduce the cause.

    The RISC CPU uses something called "minicode" to perform some operations, such as division. It effectively calls a little function to do the operation. The calling code is supposed to write the return address into the function, but I had mistakenly used the wrong build options - hence the infinite loop.

  13. #13
    Join Date
    Nov 2008
    Posts
    415

    Re: Debugging Techniques

    A given programming language may have different defaults than another language you are used to. In awk, within a function, variable scope is global by default, which needless to say can cause problems. So, a new language means new techniques are required, despite old habits.

  14. #14
    Join Date
    Jun 2005
    Location
    Montreal, Que, Canada
    Posts
    5,223

    Re: Debugging Techniques

    Hi Ocratato,

    I went a little further than just using your print statements. I used two macros.
    The first macro debug() does nothing. It does not produce any source code whatsoever. Its use is explained below.

    The 2nd macro debug1() puts out the source file name, the function name, source line number and any values you want to display,

    Code:
    #define debug(M, ...)
      /* Use debug1 where needed. Rename to debug when use is over */
       #define debug1(M, ...) fprintf(stderr, "DEBUG %s %s %d: " M "\n",__FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__ );
    Here is an example of how they are used.
    Code:
    /**
     * @brief dictionary_realloc Increase the allocation of a data dictionary field
     * @param ptr       the array to be expanded
     * @param size      array's existing size
     * @param bytes     bytes of each entry
     * @return          NULL
     */
    static void *
    dictionary_realloc (void *ptr, int size, int bytes)
    {
        void *newptr;
    
        debug ("size=%d,bytes=%d oldalloc=%d, newalloc=%d\n", size, bytes, size * bytes, size * bytes + 2);
        newptr = calloc (bytes, 2 * size);    /* one pointer for safety */
    
        if (newptr == NULL)
            fprintf (stderr, "E0001: %s: calloc (returned NULL) %s\n", __FUNCTION__, (char *) strerror (errno));
        else
        {
            debug1("%s","newptr was not NULL");
            memcpy(newptr + bytes * size, ptr, bytes * size );
            free (ptr);
        }
    
        return newptr;
    }
    The debug1 macro adds the newline at the end of the output.

    When I am satisfied with my testing/debugging of the code, I rename debug1 to debug and recompile. Obviously debug("%s","newptr was not NULL"); produces no output. Any time I need to again visit the code for more debugging, I just rename debug to debug1 and recompile.

    I try to follow some old IBM rules about messages. Every message of significance (error, warning, informationol) had an error code.
    If I received a call or email, with the message E0001, I knew immediately, how it was produced and where to look in the source files.
    Leslie in Montreal

    Interesting web sites list
    http://forums.fedoraforum.org/showth...40#post1697840

  15. #15
    Join Date
    Oct 2010
    Location
    Canberra
    Posts
    2,952

    Re: Debugging Techniques

    Quote Originally Posted by dswaner
    A given programming language may have different defaults than another language you are used to. In awk, within a function, variable scope is global by default, which needless to say can cause problems. So, a new language means new techniques are required, despite old habits.
    Oh yes. I remember the fun of writing in C at work and Modula-2 at home: assignments and equality tests could result in much gnashing of teeth.
    C = and ==
    Modula := and =

    At least the compiler finds these errors.

Page 1 of 3 1 2 3 LastLast

Similar Threads

  1. Header Compression techniques Ethernet links
    By rpdumps in forum Using Fedora
    Replies: 0
    Last Post: 30th June 2008, 06:58 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •