C++ Rule of Zero – How to Debug Object Construction

cdebuggingrule-of-threevisual studio

Everyone is quick to point out the "Rule of Zero" in code reviews, peer conversations, and Stack Overflow comments/answers.

I am not a believer. I'd like to be. Usually if enough people agree on something enough for it to get its own label and become an idiom, then it is well thought out….

So, let me explain my reason for not believing:

I cannot count the number of times I have been tasked to debug a crash dump from a production crash. While debugging said dump, I can look up and down the call stack and sometimes I have the need to see "When is this class being constructed?" Secondarily, I might need to see "What is its or its members addresses when it is?" This usually leads to some other place in the code after evidence that more instances are being created than should be, or when addresses or sizes are not what is expected.

This could also apply, when I want to see "When is this class being assigned to?"

As such, I've always implement all 5 methods, trivial or not, in order to provide a place to break in future debug sessions while reproducing the conditions in the dump without having to change the source. Without them, there would be no way (easily) to perform the above debugging session.

If you modify source in order to provide a line of code to break on, your crash dump is no longer usable with the source.

Now, some would say that this situation does not arise often enough for them to add more code, and more potential bugs, in the case of trivial constructors and assignment operators. However, I'd argue that one occasion having to explain to your superiors that you have to make another build, redeploy to production, reproduce the crash, and retrieve another dump, in order to even start debugging the problem, is enough to change one's outlook. That is not an enjoyable experience and it has occurred to me a number of times.

So, please make me a believer!

Tell me how I can accomplish the above described debugging session given a crash dump, when there is no line available to break on, after being a good boy and following the "Rule of Zero".

Namely:

  1. Break any time any instance of a given class is being constructed without any lines of constructor code to break on.

  2. Break any time any instance of a given class is being assigned to without any lines of assignment operator to break on.

I am using Visual Studio, and more specifically Visual Studio 2015.

Best Answer

After much debate, many lunches, posts on various forums, and head scratching, a colleague of mine came up with the following:

In Visual Studio, go to Debug->New Breakpoint->Function Breakpoint and enter the fully qualified name of the compiler generated method you wish to break on. For example Foo::Foo will break in Foo's compiler generated default constructor. We can add Foo::Foo(const Foo &) for its copy constructor, Foo::Foo(Foo &&) for its move constructor, etc. Note that you must also include any namespace. Also note that you can add function names that do not exist. Take note of the opaque red dot in the breakpoints window vs empty circle denoting a point that will not get hit.

After the debugger breaks, we can use the callstack window to identify what it broke on and choose to continue or not. If we wish to inspect then we can open the disassembly window and step (F10) to the point the constructor, copy constructor, assignment, etc is complete. We can look for the "ret" instruction to guide us. When it goes one up the call stack, even in the disassembly window, the name of the method is denoted. We can then switch to Locals and view "this" as normal.

This is, of course, specific to Visual Studio. Other debuggers might have something similar.

Related Topic