I hate debugging - I would much rather write code or watch tests execute! Debugging is a waste of time, and often follows an unpredictable path. Any developer knows the situation: A bug is discovered, and the cause must be found. Most developers have these war stories on how they fought with a bug. The battle swung back and forth. Theories were tested and discarded, instrumentation was built, log files were examined, Murphy visited and, coffee was spilled. When the stories are told, they typically have a happy ending, so eventually the Eureka-moment occurred and the cause was found. And a debugging lesson was learned.
One of my toughest debugging session spanned almost 2 weeks. My code was complete and ready for check-in. I had worked on it for about 2 months in a private branch. Before reverse integrating into the main branch I ran all unit tests. A successful run takes about 12 hours. In my case the execution crashed after about 10 hours. I tried to run the single test case that crashed in isolation. It passed. I tried again with the full automation. It still crashed. I then tried disabling the crashing test, just to realize 10 hours later, that now a different test crashed. I then tried running with a debug version of AX32, so I could debug the crash. But the debug build is much slower, so it would take ages before the crash happened. So I needed to isolate the crash in a simpler repro. I tried changing the order of tests, and with every change I made the crash moved somewhere else. I then began trawling the system logs for information about the crash. This lead me to think about memory – perhaps something was leaking memory. I instrumented the test automation, so it would dump the current memory footprint every 10 seconds to a log file. And yes – memory consumption climbed until the crash occurred. But hey; I’m just writing X++ code – what can I possibly do that causes memory to leak? Driving home one day I got the idea that perhaps it was not my code, but the X++ runtime. After all; I was using some of the not-yet-released-at-this-point X++ features pretty heavily (attributes and events). So I wrote a small job, that exercised these areas heavily, and I saw memory climbing slowly but steadily until the crash. Now with a simple repro in hand, it was not hard to solve the issue – but I did require help from my friends in the X++ team. Two weeks had passed before I was ready to submit, my code was exactly the same, and now all test passed.
This X++ debugging series of posts is dedicated to share X++ debugging tips and tricks. Having a toolbox full of different ways to attack bugs is required to be a productive developer. I’m going to share some of my tricks. If you have tricks of your own, please write a comment, and I will include them in the series. The ultimate goal is that we all efficiently find and solve X++ bugs.
Trick #1 – Breakpoint in Info.add()
Trick #2 – xSession::xppCallStack()
Trick #3 – Conditional breakpoints
Trick #4 – Reading uncommitted data
Trick #5 – To be announced
This trick is probably the first every X++ developer learns, so it deserves to be the first on the list of X++ Debugging Tips and Tricks.
Suppose an X++ exception occurs and you want to know why. The error is written to the Infolog. Double-clicking the line in the Infolog window will bring you to the line that threw the exception. Sometimes it is trivial to see the cause just by looking at the code. Other times it is not, and you will need the entire context including the call stack and variables to figure out what the cause is.
Set a breakpoint in the add method on the Info class – and rerun the scenario. When the exception is thrown your breakpoint is hit, and you can perform the autopsy.
This post is provided AS-IS, and confers no rights or warranties.