Thread: How can I improve my debugging of off-by-ones in C?

  1. #1
    Old Fashioned
    Join Date
    Nov 2016
    Posts
    137

    Question How can I improve my debugging of off-by-ones in C?

    I've been programming in C for 2-3 years now and I use it professionally at work as well.

    One sticking point for me that I've seen happen over and over is I'd like to improve at debugging off-by-one type errors. I'm going to use an example program that I wrote a couple days ago as an example:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    void reverse_arr(char *arr, size_t len);
    void print_chars(char *arr, size_t len);
    void reverse_words(char *arr, size_t len);
    int main(int argc, char **argv)
    {
        char phrase[] = {'p','e','r','f','e','c','t',' ',
                        'm','a','k','e','s',' ','p','r',
                        'a','c','t','i','c','e'};
            size_t i;
        
        reverse_arr(phrase, sizeof(phrase));
        reverse_words(phrase,sizeof(phrase));
        print_chars(phrase, sizeof(phrase));
        return EXIT_SUCCESS;
    }
    void reverse_arr(char *arr, size_t len)
    {
        size_t front, tail;
        tail = len-1;
        char tmp;
        for(front = 0; front < len/2; front++, tail--)
        {
            tmp = arr[front];
            arr[front] = arr[tail];
            arr[tail] = tmp;
        }
        return;
    }
    // 1. Search for a space
    // 2. When space is found, that space is the place to stop and indicates all between the start and it are a word
    // 3. Now call reverse_arr on the word and calculate the length of the word by subtracting tail - start
    // 
    void reverse_words(char *arr, size_t len)
    {
        size_t tail, start;
        for(tail = start = 0; tail < len; tail++)
        {
            if(arr[tail] == ' ' || tail == len-1)
            {
                reverse_arr(&arr[start], tail - start);
                start = tail+1;
            }
        }
    }
    void print_chars(char *arr, size_t len)
    {
        size_t i;
        for(i = 0; i < len; i++)
        {
            putchar(arr[i]);
        }
        putchar('\n');
        return;
    }

    I was banging my head on this for hours trying to troubleshoot my counters and loop conditions.. I did make some small progress but this again made me realize I could improve my skills. The answer was that the function needed to be changed to this:

    Code:
    void reverse_words(char*arr,size_t len) { size_t tail, start; for(tail = start =0; tail <= len; tail++) { if(tail == len || arr[tail]==' ') { reverse_arr(&arr[start], tail - start); start = tail+1; } } }


    The if test needed to be reversed and the loop condition needed to change from < to <=.

    My question is, what types of debugging techniques would you use to find the answer for this in a reasonable amount of time? I tried printfs on the counter variables as well as using gdb and watches, breaking on the entry of the reverse_words() function.

    I've noted that in C, this is a common occurrence due to the manual looping process versus Python which handles most of these cases for the programmer. But rather than run away from C, I'd like to improve in this area. C also tends to lend itself to very dense code like that in K&R C and while many people say "don't program like that and don't use codebases like that,"

    A) I don't have that luxury. I'm a software security engineer and there are several programmers at work who write very cryptic code that I have to work with.

    B) I actually find the compact nature of K&R style code to be fascinating and I'd like to get better at understanding and writing it in some cases.
    Last edited by Asymptotic; 06-01-2019 at 02:01 PM. Reason: Formatting fix
    If I was homeless and jobless, I would take my laptop to a wifi source and write C for fun all day. It's the same thing I enjoy now!

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    27,922
    I think you copied and pasted your code using a custom syntax highlighting option, and as a result it's all wonky and unreadable when posted here.

    Maybe one thing you could try is to write unit tests first with the corner cases, so if you do make an off-by-one error it's more likely you'll catch it in a related corner case.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Old Fashioned
    Join Date
    Nov 2016
    Posts
    137
    Ah ok sorry I just "fixed" it... Still a color but at least it's visible now lol.
    If I was homeless and jobless, I would take my laptop to a wifi source and write C for fun all day. It's the same thing I enjoy now!

  4. #4
    Registered User catacombs's Avatar
    Join Date
    May 2019
    Location
    /home/
    Posts
    81
    The code is still in some weird serif font. It makes the code hard to read.

  5. #5
    Old Fashioned
    Join Date
    Nov 2016
    Posts
    137
    Quote Originally Posted by catacombs View Post
    The code is still in some weird serif font. It makes the code hard to read.
    Ok should be fixed for real now.
    If I was homeless and jobless, I would take my laptop to a wifi source and write C for fun all day. It's the same thing I enjoy now!

  6. #6
    Registered User
    Join Date
    Feb 2019
    Posts
    719
    Sometimes you don't need a counter. For instance, your reverse_arr() function could be written like this:
    Code:
    #define swapch(a,b) { char t; t = (a); (a) = (b); (b) = t; }
    
    void reverse_arr( char *ptr, size_t len )
    {
      // for debuging purposes only (define NDEBUG to get rid of it).
      assert( len > 0 );
    
      char *endp = ptr + len - 1; // points to the last element.
    
      while ( endp > ptr )
      {
        swapch( *ptr, *endp );
        endp--; ptr++;
      }
    }
    This will create a smaller code (maybe!) and a faster one (for sure!), since the case where you have an even 'len' will not copy the middle element on itself.

  7. #7
    Registered User
    Join Date
    Feb 2019
    Posts
    719
    Here's a simple and easy to spot errors replacement to your print_chars() function:
    Code:
    void print_chars( char *ptr, size_t size )
    {
      while ( size-- )
        putchar( *ptr++ );
    
      putchar( '\n' );
    }

  8. #8
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,877
    Where are you writing this code?
    i.e.
    Windows codeblocks
    iOS xcode
    PIC XC8
    ...?

  9. #9
    Old Fashioned
    Join Date
    Nov 2016
    Posts
    137
    Quote Originally Posted by Click_here View Post
    Where are you writing this code?
    i.e.
    Windows codeblocks
    iOS xcode
    PIC XC8
    ...?
    I write C code on Windows, macOS, and Linux using Visual Studio Code and GCC. I typically avoid the OS-specific APIs unless absolutely necessary.
    If I was homeless and jobless, I would take my laptop to a wifi source and write C for fun all day. It's the same thing I enjoy now!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. How would you improve it?
    By cooldude1 in forum C Programming
    Replies: 5
    Last Post: 07-26-2010, 02:54 AM
  2. Help me to Improve
    By epi_jimenez in forum C Programming
    Replies: 7
    Last Post: 04-17-2009, 05:11 PM
  3. How can I improve this?
    By Raigne in forum C++ Programming
    Replies: 2
    Last Post: 04-19-2008, 01:30 AM
  4. How to Improve?
    By tallguy in forum C++ Programming
    Replies: 1
    Last Post: 04-03-2007, 05:59 AM
  5. how to improve
    By blight2c in forum C++ Programming
    Replies: 5
    Last Post: 04-03-2002, 07:31 AM

Tags for this Thread