Welcome to MSDN Blogs Sign in | Join | Help
4 Hours To Find Out It's Someone Else's Problem

Sometimes, the reward of your investigation is finding out someone else has to do the hard job of actually fixing the problem.

The Background

The bug I was tasked with solving was this:

Add a word to a shape, double click the text, do this specific operation and the text selection disappears.

Doesn’t happen if just select part of the text. Doesn’t happen if you select all of the text. Only happens if you double click the text.

“What could possibly be the difference?” I noted to myself.

Well, as it turns out, all text bodies have a carriage return at the end. This is used for a variety of things, most notably for indicating a new line. However, even single lined text bodies have a carriage return.

The difference then between double clicking and selecting all is that double clicking a word selects only that word. You can try this in PowerPoint 2007:

 

To the left is the text selected after double click, to the right is the carriage return that isn’t selected in the text to the left.

As you can imagine, carriage returns, being invisible, could cause some user frustration if they aren’t handled correctly.

One thing to do is to make sure that the formatting of the carriage return matches the text that’s next to it.

Take this scenario: double click a single word, hit CTRL+B. Now the UI says your current text is bold by showing the bold button as pressed the bold button. Now hit CTRL+A to select all the text, including the carriage return. The UI still says your text is bold, even though when you applied bold you didn’t have the carriage return selected.

Which leads us to this bug.

The Investigation

There are many, many things I tried to see what was going on. Some of my usual tricks:

-          Place a breakpoint that I think will only be hit when the code is in a good state. Then trace through the stack and see where we diverge in the bad state.

-          Place a breakpoint that I think will only be hit when the code is in a bad state. Then trace through the stack and see why it’s bad.

Nada. Every place I try I always get the same call stack.

Other things to try:

-          Trace through at a time when I know the code is in a good state, watch the screen and see if I can tell when it becomes bad. Since the selection was disappearing maybe I could catch the call that was clearing it.

No good, screen update happens way after the problem has occurred.

-          Place breakpoints in all methods of the offending class, check incoming data to see if the selection is getting put into a bad state.

All good. In fact it’s too good, as in the data being passed in does not match the data I see on the screen after the bug.

I did manage to find a place in code though that showed the bad state when getting the value. So the Set method puts the correct value in Get retrieves a different, bogus value.

Hmm.

-          Place filter points to see when the data is actually changing.

-          Remote debug so I can place breakpoints between setting the selection and doing the operation (because any change to the selection means it would hit my breakpoints, thus breaking too early)

I finally narrow down which member variable is the getting changed incorrectly.

-          Place memory breakpoints to see when member variable is getting changed.

But this variable is actually a complex class. And the data is stored in a collection class and thus doesn’t have a nice “&var.m_value” that I can add to the debugger.

After fooling around with it for a good 45 minutes trying to get the raw pointer from the collection, I decide to take a chance that the entity in the collection isn’t moving around or being deleted. So I add some code which calls into the entity, I debug into it before the bug occurs and I set a memory break point using its “this” pointer.

Tada.

The Bug

Visual Studio breaks in some code that I’ve never seen before. But sure enough, it has “entity.value = iterator.m_value”. This all happened internally to the storage class explaining why the Set method put one value and the Get method gets another.

From here on it takes my about 10 minutes to find the problem (after 4 hours of trying to hit the square mile the problem was on from Earth orbit).

I finally found the place where the code diverges from good to bad state:

                if( selectionLength == bodyLength )

           // do thing in good state

      else

           // do thing in bad state

A little more searching, and I found the function that extends the selection from the last character to include the carriage return. The problem with the code above is that it doesn’t take into account that selectionLength could be one shorter than bodyLength.

The good news is I found the problem.

The bad news is that I have very little experience in this part of the code.

The good news is that another team owns the code!

The bad news is I wanted the problem fixed tonight and now I have to wait until someone else gets around to fixing it.

None the less, I feel accomplished for the day.

Posted: Friday, October 05, 2007 7:17 AM by Chris Becker
Filed under: ,
Leave a Comment

(required) 

(required) 

(optional)

(required) 

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Page view tracker