3

I have a hierarchy of objects, mostly connected by composition. I.e. (not showing the class methods for readability):

class A {}
class B {A a;}
class C {B b;}
etc...
class Z {Y y;}

class Z provides the API for executing commands from another program - a control panel. I think this is called Chain of Responsibility, but might be at an error.

Now when an action on A needs to be performed, Z calls a method of Y, because Z knows only about Y. So on, until we reach A, which has the proper members and methods to handle the request.

This has the fundamental problem that debugging becomes tedious - one has to step in many times, and each time be careful not to miss the actual working method - otherwise the debugging session needs to be restarted.

How do I make debugging more straightforward? A change in the architecture of a method of using gcc that is more suited to this situation?

3
  • 6
    use breakpoints in the A class? Commented Oct 31, 2014 at 10:11
  • You can't, because the error might be in any of the classes. So you have to go through all the classes and search for the method call which get's the correct arguments but does not do or return what it should. There is no way around this. Unless you know from the beginning which method produced the wrong result. In this case, do like ratched freak said and use breakpoints there. Or even better: make class A so that it always returns the same result when given same arguments. You can then directly call A with these arguments and check the result. Commented Oct 31, 2014 at 10:43
  • Would instead of writing wrappers, using using solve my problem? Commented Oct 31, 2014 at 13:02

2 Answers 2

6

When you split up big methods into smaller ones, and separate concerns to many classes, and write more functions with clearly separated levels of abstraction, you will end up with long call chains, that's true. But when you choose your abstractions well your code becomes much more readable and understandable than the typical 200 lines-of-code-spagetthi function.

And readable code avoids a lot of bugs at first hand, so to my experience this outweighs the increased debugging efforts caused by the call chains by a multitude. So my advice is: live with it. Don't use this "long call chains make debugging harder" argument as an excuse for not refactoring your code into smaller functions, such reasoning leads always to a fallacy.

As a hint for debugging when you accidentally missed the cause of an error: some debuggers (like gdb) allow you to "undo" your last steps in the middle of a debugging session.

3
  • In Visual Studio you can simply drag the "current instruction" arrow to you the line you want to execute next. Commented Oct 31, 2014 at 12:40
  • @JohannesS.: you are correct, but the OP was talking about GCC, not about VS. Commented Oct 31, 2014 at 13:01
  • 1
    Ah, sorry, missed this because I only had a quick look at the tags Commented Oct 31, 2014 at 14:34
1

Use logging. (I don't know what are logging options in c++, but i would be surpirsed if there wasn't something close to what is available in Java).

Log entering and exiting method and what is going in/out (and either do it in configurable automatic way, or only in interesting places). This way you know where it went and if you can formulate postconditions and preconditions, you can check them when going through logs to find where something strange is happening and then put breakpoint to the right place.

When same method is called repeatedly and only after log run it breaks down on border case, you can use conditional breakpoint, because you know (from logs) what data causes problem.

This will require multiple runs to examine problem, but log run will be without manual steping, so much faster, and in debug run you will start closer to actuall problem (or at least its closer to its manifestation.

3
  • It's an embedded project and storing and retrieving logs sounds problematic. We have a display, to which we write when an assert() fails. Commented Oct 31, 2014 at 12:04
  • @Vorac: Especially in embedded devices logging is nearly indispensable. Usually there is a serial port used for debug output and you could send the logging there too and analyse it off-line. Commented Oct 31, 2014 at 19:13
  • Unfortunately the HW guys are too lazy to connect the appropriate pins to a header. I have USB and JTAG available. Commented Nov 3, 2014 at 12:32

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.