Jump to content
  • Advertisement
Sign in to follow this  
Endar

Your debugging reasons

This topic is 4867 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I just finished debugging a problem with something I'm working on, and I found out that, now, like it is often, the problem was because I forgot to include something, or instead of an '<' sign, I have '<='. So, here's the question. Do you usually find that after debugging and solving your problems that the problems are because of something in the method of solving, or something small such as forgetting to include a specific operator or a line of code?

Share this post


Link to post
Share on other sites
Advertisement
the last x reasons to debug for me:
  • stupid single letter variable names
  • diffrent function signatures when trying to overload an inherited function
  • MSVC7.1 dependancy checker failing horribly and not recompiling all dependant code

    Share this post


    Link to post
    Share on other sites
    I debug all the time regardless of whether or not there's a problem. If I finish writing a class, I'll add it to the project and step through it - making sure that everything's behaving as it's supposed to (as well as noting some possible problems that might have the potential to show up in the future).

    It takes time, but I'm a hobbiest programmer, and I hate not making things clean and bug-free from the start.

    Needless to say, I haven't come across an annoying bug in ages. Logic bugs are usually (but not always) caught during these debugging phases.

    Share this post


    Link to post
    Share on other sites
    Here are the details of the bugs in my current C project:


    • ;Inversion of for loop arguments due to low readability in a macro (*) (x)
    • Not freeing the memory of objects in a function of the type while(cond) { a = get( ); free( a ); } (*) (x)
    • Not freeing the memory of objects in a function of the type foo(a) { bar(a); free(a); } (*) (x)
    • Uninitialized variable. (*) (x)
    • %d used in place of %f in a printf format string (*) (x)
    • Two functions with the same name and signature in two different librairies not being marked as static. (*) (x)
    • Misunderstanding of API documentation and absence of asserts before dereferencing a NULL pointer.
    • Incrementing the wrong variable in the inner loop of a two-level for loop. (x)
    • Side-effect causing the reallocation of a dynamic array, making pointers to the previous array position useless. (x)
    • Missing allocation or initialization of complex structures. (x)
    • Alignment issues (trying to read or write unaligned memory). (x)


    Errors marked with an (*) were detected through the use of unit tests. The others were noticed because of crashes during normal execution. Errors marked with an (x) could not have happened in Objective Caml.

    Here are the bug details of my current Objective Caml project (all of them have been detected through unit testing):


    • Using < insead of > or <=.
    • Error in repeated Bernouilli trials formula.
    • Inversing the then and else code blocks.
    • Not respecting API requirements which called for associative-commutative function, but a non-commutative non-associative function was passed.
    • Forgetting to implement exception throwing in the case of a negative value being returned.

    Share this post


    Link to post
    Share on other sites
    Most of the time I find my problems are logic related. Every once in a while though I'll use = instead of == in an if statement. That one usually causes lots of time trying to fix since it isn't something I'm used to looking for.

    I have found over time that the best way to debug is to test every class that you write as soon as you are done writing it. It may seem like it would take more time to do, but the amount of time you spend actually hunting for bugs decreases a lot if you know where the problem should be when you start.

    Share this post


    Link to post
    Share on other sites
    * APIs that do not behave as documented (most annoying issue) (and of course APIs that simply aren't documented and don't behave as one would assume)
    * Memory alignment/byte order issues
    * Midnight coding problems (usually boils down to assumptions about APIs without checking documentation)

    Hmm... I can't think of anything else that I've run across recently.

    Share this post


    Link to post
    Share on other sites
    Thankfully, I've not run across typo bugs in quite some time.

    The sort of things that caused bugs in the past week:

    - Made a function to trigger another event based on grouping rules. Certain rules inadvertantly triggered the function again before it had time to clean up, causing an infinite loop. *boom* [stack overflow crash]

    - Made a functor to delete an object, which would generally be called from a triggering event, which is from input generally, which is handled in rendering. Well deletion removes the object from rendering. If the triggered deletion was called from the same area as the object in question, it invalidated iterators in the group... As the stack unwound back to rendering it tried to use the [now invalid] iterator. *boom* [Iterator not incrementable]

    Share this post


    Link to post
    Share on other sites
    Last unit I was debugging would be my forced-endian integer classes which I was refactoring from a pair of classes which shared much copy/pasted code to a single flexible policy based class (which shared said code instead of copy/pasted). Found out I couldn't (in MinGW GCC 3.4.2) inherit typedefs from a template argument even with the typename syntax apparently... I had something similar to:

    struct default_base_endian_integer_policy {
    typedef unsigned long value_type;
    typedef unsigned char indexed_value_type;
    typedef size_t size_type;
    };

    template < typename base_policy = default_base_endian_integer_policy >
    struct big_endian_integer_policy : base_policy {
    ...attempt to use value_type, indexed_value_type, and size_type...

    Fixed by changing my code:
    template < typename base_policy = default_base_endian_integer_policy >
    struct big_endian_integer_policy {
    typedef typename base_policy::value_type value_type;
    ...

    In the original test I uncovered a typeo (which caused an assert failure when it compared 0x24 == 0x34)

    Share this post


    Link to post
    Share on other sites
    Most of my runtime problems are algorithmic.

    Most of my compile time problems are design issues. I compile as often as I can, and when I change interfaces a lot of errors pop up that are usually easily fixed.

    The hardest bugs happen at runtime and usually involve memory allocation/deallocation/improper use.

    Share this post


    Link to post
    Share on other sites
    Quote:
    Original post by Endar
    Do you usually find that after debugging and solving your problems that the problems are because of something in the method of solving, or something small such as forgetting to include a specific operator or a line of code?


    Almost always in the method of solving. Sometimes it's forgetting to include a specific operation, sequence of operations, etc. But not usually because of forgetting an operator or one line of code.

    For example, QA recently reported this bug:

    1. Create a clan.
    2. Have the clan ranked in the top 10.
    3. Leave the clan so that it no longer exists.
    4. Notice that in the "Top 10 Clans" section of stats and rankings, the clan's ranking still remains, but the clan name is replaced with "<>."

    I always test my code, but QA exists precicely because it can catch these kinds of things when I may not when I'm just stepping through code. As it turns out, there's a known and undocumented bug in a library that was causing this behavior. The solution involved setting the clan's stats to an invalid number and then catching that special case and displaying something more appropriate in the UI.

    That said, I do make my fair share of errors regarding null pointers or reversed logic or even build configurations (maintaining three platforms can be annoying when you only use one of them), but I usually catch those fairly quickly and they don't really register on my radar as anything more than background noise.

    For example, I was just adding some quick logging functionality to a couple of functions. I was trying to fprintf a MAC address, which was stored as byte[6], and it didn't look right. When I finally took the time to step through and watch the data, I realized that I was printing the right numbers, but I just needed to use %02x instead of %x... Actually, I had a series of issues with fprintf since I don't use it much. Using %S versus %s and the ins-and-outs of using %I64 :)

    Share this post


    Link to post
    Share on other sites
    Sign in to follow this  

    • Advertisement
    ×

    Important Information

    By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

    We are the game development community.

    Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

    Sign me up!