<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Buggin' My Life Away : Programming</title><link>http://blogs.msdn.com/rick_schaut/archive/tags/Programming/default.aspx</link><description>Tags: Programming</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Craig's Bug</title><link>http://blogs.msdn.com/rick_schaut/archive/2008/01/31/craig-s-bug.aspx</link><pubDate>Fri, 01 Feb 2008 05:01:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7363990</guid><dc:creator>Rick Schaut</dc:creator><slash:comments>9</slash:comments><comments>http://blogs.msdn.com/rick_schaut/comments/7363990.aspx</comments><wfw:commentRss>http://blogs.msdn.com/rick_schaut/commentrss.aspx?PostID=7363990</wfw:commentRss><description>&lt;!--StartFragment--&gt;&lt;p class="MsoNormal"&gt;One of the things I love about this job is tracking downinteresting bugs.&lt;span style="mso-spacerun: yes"&gt;  &lt;/span&gt;It’s like readinga good who-done-it, complete with plot twists, multiple potential suspects and a fascinating array of characters.&lt;span style="mso-spacerun: yes"&gt; &lt;/span&gt;Late last September, Craig Eisler submitted a bug that had all of these elements.&lt;/p&gt;&lt;p class="MsoNormal"&gt;Now, when your general manager submits a bug, you don’t necessarily have to get on it right away.&lt;span style="mso-spacerun: yes"&gt; &lt;/span&gt;But, it’s not a good idea to let it linger for too long.&lt;span style="mso-spacerun: yes"&gt;  &lt;/span&gt;So, after this bug had been on the list for about a week or so, I decided it was time to figure out what was up.&lt;/p&gt;&lt;p class="MsoNormal"&gt;The bug involved a document Craig had been editing with revision marking turned on.&lt;span style="mso-spacerun: yes"&gt;  &lt;/span&gt;He’d made some changes to the document, saved it, quit Word and, when he opened the document back up, some of the spaces between words were missing.&lt;/p&gt;&lt;p class="MsoNormal"&gt;With a bug like this, the first thing I do is open it up in Win Word.&lt;span style="mso-spacerun: yes"&gt;  &lt;/span&gt;If the problem appears there, then there’s a strong likelihood that the bug is in the code that writes the file.&lt;span style="mso-spacerun: yes"&gt;  &lt;/span&gt;If the bug doesn’t appear in Win Word, then I know to start looking at the code that reads files.&lt;span style="mso-spacerun: yes"&gt;  &lt;/span&gt;In this case, the problem appeared in Win Word, so my first suspect is going to be somewhere in the save code.&lt;/p&gt;&lt;p class="MsoNormal"&gt;Also, the missing spaces seemed to be in or around areas of the document where revisions had been made.&lt;span style="mso-spacerun:yes"&gt;  &lt;/span&gt;So, the first suspect was somewhere in the code that writes revisions.&lt;span style="mso-spacerun: yes"&gt;  &lt;/span&gt;I created a document, added some text, turned on revisions made some changes and saved the file stepping through the code that handles revision marking.&lt;/p&gt;&lt;p class="MsoNormal"&gt;Nothing.&lt;span style="mso-spacerun: yes"&gt;  &lt;/span&gt;Everystep along the way, everything was happy.&lt;span style="mso-spacerun: yes"&gt; &lt;/span&gt;The code was writing all the appropriate XML tags, and none of the text was missing.&lt;span style="mso-spacerun: yes"&gt;  &lt;/span&gt;Of course those two sentences summarize about two-three hours of sleuthing, after which I was able to exclude the revision marking save code as a suspect.&lt;/p&gt;&lt;p class="MsoNormal"&gt;Well, maybe it’s something that only appears to be related to revision marking.&lt;span style="mso-spacerun: yes"&gt;  &lt;/span&gt;Let’s take two files, one that exhibits the problem and one that doesn’t, and compare the contents (much easier to do now that the document content is XML).&lt;/p&gt;&lt;p class="MsoNormal"&gt;Again, nothing.&lt;span style="mso-spacerun: yes"&gt; &lt;/span&gt;Other than a few gratuitous differences (revision save ID’s, for example, which are uniquely generated every time new text is saved in a document), everything in and around the missing spaces was identical.&lt;span style="mso-spacerun: yes"&gt;  &lt;/span&gt;Another couple of hours spent cracking open various documents and comparing the XML, and I still haven’t a clue whothe real culprit is.&lt;/p&gt;&lt;p class="MsoNormal"&gt;Well, but, if the documents are identical, maybe the problem happens when we read the file.&lt;span style="mso-spacerun: yes"&gt;  &lt;/span&gt;So, I set a breakpoint on the code that handles runs of text from the XML parser, and, sure enough, our “characters” callback wasn’t getting called for just the missing spaces.&lt;span style="mso-spacerun: yes"&gt;  &lt;/span&gt;Hm…&lt;span style="mso-spacerun: yes"&gt;  &lt;/span&gt;Progress.&lt;/p&gt;&lt;p class="MsoNormal"&gt;About another hour or so, I had tracked it down to some general XML parsing code we’d ported from Win Office.&lt;span style="mso-spacerun:yes"&gt;  &lt;/span&gt;One of the problems with writing filing code that’s intended to handle future situations is that, when you write the code, the future hasn’t arrived yet.&lt;span style="mso-spacerun: yes"&gt;  &lt;/span&gt;Well, for Win Office, Mac Office represented the future, and some of the stuff we’d added exposed a subtle bug in the code we’d ported (note: the problem has been fixed in WinOffice before Mac Office shipped, so people shouldn’t run into this at all).&lt;/p&gt;&lt;p class="MsoNormal"&gt;By the time I had finished all of this, implemented a fix and verified the fix, it was about 1:30 in the morning.&lt;span style="mso-spacerun: yes"&gt;  &lt;/span&gt;When I get engrossed in a good mystery, I sometimes find it difficult to put the book down.&lt;span style="mso-spacerun:yes"&gt;  &lt;/span&gt;Same thing goes with good mystery bugs.&lt;/p&gt;&lt;p class="MsoNormal"&gt;And, the bug being a good mystery bug that geeks like Craig and I appreciate, I sent off an e-mail to Craig outlining the basic nature of the bug and the fix (which turned out to be just a couple lines of code—this is almost always the case with a good mystery bug).&lt;span style="mso-spacerun:yes"&gt;  &lt;/span&gt;This being in the middle of the FIFA Women’s World Cup, I ended the mail by saying that I was going to go home, drink some coffee, and stay up to catch the USA match (I forget who the opponent was).&lt;/p&gt;&lt;p class="MsoNormal"&gt;The next day, I got a response from Craig with some questions about the bug.&lt;span style="mso-spacerun: yes"&gt;  &lt;/span&gt;I replied to Craig’s questions and, at the end of the e-mail, lamented over the fact that, after all that effort and all that coffee to stay up to watch a soccer match, our local cable company saw fit to pre-empt the last 30 minutes of the match with a taped question-and-answer program starring Mike Holmgren, the Seahawks coach.&lt;/p&gt;&lt;p class="MsoNormal"&gt;For a born-in-Green-Bay, prick-me-and-I-bleed-green-and-gold, Packers fan like me, having a soccer match for which I’d stayed up all night to be able to watch be preempted by Mike Holmgren is seriously rubbing salt into the wound, and I conveyed my displeasure at this to Craig by saying that the only reason we still have a working television in the house is the fact that there were people asleep in the house at that time.&lt;/p&gt;&lt;p class="MsoNormal"&gt;What ensued was a series of e-mails between Craig and I with a dual thread about the bug he’d reported and my television set.&lt;span style="mso-spacerun: yes"&gt;  &lt;/span&gt;His response to my previous e-mail was to suggest that I should have taken the TV outside and smashed it there.&lt;span style="mso-spacerun: yes"&gt;  &lt;/span&gt;Wake up the neighbors instead of the kids, and I get to vent my hostilities.&lt;/p&gt;&lt;p class="MsoNormal"&gt;In my reply, I explained that this was not an option giventhe size (36”) and weight (over 260 lbs) of my TV set, to which Craig replied, “A CRT!?&lt;span style="mso-spacerun: yes"&gt;  &lt;/span&gt;How quaint!&lt;span style="mso-spacerun: yes"&gt;  &lt;/span&gt;Do you get slivers when you go to the bathroom after watching that TV?”&lt;/p&gt;&lt;p class="MsoNormal"&gt;Having an uber-geek general manager is cool.&lt;span style="mso-spacerun: yes"&gt;  &lt;/span&gt;You get great bug reports, and he likes to hear about the nature of the bug and the fix.&lt;span style="mso-spacerun:yes"&gt;  &lt;/span&gt;Just be a little careful when you talk about the technology around your house.&lt;/p&gt;&lt;p class="MsoNormal"&gt; &lt;/p&gt;&lt;p class="MsoNormal"&gt;Rick&lt;/p&gt;&lt;p class="MsoNormal"&gt;Currently playing in iTunes: New World Blues by Gov't Mule &lt;/p&gt;&lt;!--EndFragment--&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7363990" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/rick_schaut/archive/tags/Programming/default.aspx">Programming</category><category domain="http://blogs.msdn.com/rick_schaut/archive/tags/Mac+BU/default.aspx">Mac BU</category></item><item><title>There Comes a Time</title><link>http://blogs.msdn.com/rick_schaut/archive/2007/04/04/there-comes-a-time.aspx</link><pubDate>Thu, 05 Apr 2007 04:48:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2028545</guid><dc:creator>Rick Schaut</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/rick_schaut/comments/2028545.aspx</comments><wfw:commentRss>http://blogs.msdn.com/rick_schaut/commentrss.aspx?PostID=2028545</wfw:commentRss><description>&lt;P&gt;In every project, there's a point where you have to stop tweaking this and touching up that little bit of behavior and focus on just fixing bugs.&amp;nbsp; If you don't, then you never ship.&amp;nbsp; Nadyne &lt;A href="http://blogs.msdn.com/macmojo/archive/2007/03/15/ship-it.aspx" mce_href="http://blogs.msdn.com/macmojo/archive/2007/03/15/ship-it.aspx"&gt;gave some of the details&lt;/A&gt; over on &lt;A href="http://blogs.msdn.com/macmojo/" mce_href="http://blogs.msdn.com/macmojo/"&gt;mac mojo&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;Well, we're getting close to that time with Mac Office 12.&amp;nbsp; In honor of nearing such a milestone, I prepared something for our program management friends.&amp;nbsp; These are the folks who are responsible for designing how the various features are supposed to behave from the user's point of view.&amp;nbsp; It's a suggestion box, and it looks like this:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/rick_schaut/WindowsLiveWriter/ThereComesaTime_10853/x1pXjQifqRFQ7oxMft2jDMrP9HH8Kqo184YJQf544Mm9SSDVMW8Z9R0BXcQfqgcJGQzuG5OTcWCwEsoCavOFSCufuZ-0q00wHlc1U0xlbyMp9izeXB2FpLMgQ%5B1%5D%5B1%5D.jpg" atomicselection="true" mce_href="http://blogs.msdn.com/blogfiles/rick_schaut/WindowsLiveWriter/ThereComesaTime_10853/x1pXjQifqRFQ7oxMft2jDMrP9HH8Kqo184YJQf544Mm9SSDVMW8Z9R0BXcQfqgcJGQzuG5OTcWCwEsoCavOFSCufuZ-0q00wHlc1U0xlbyMp9izeXB2FpLMgQ%5B1%5D%5B1%5D.jpg"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=192 src="http://blogs.msdn.com/blogfiles/rick_schaut/WindowsLiveWriter/ThereComesaTime_10853/x1pXjQifqRFQ7oxMft2jDMrP9HH8Kqo184YJQf544Mm9SSDVMW8Z9R0BXcQfqgcJGQzuG5OTcWCwEsoCavOFSCufuZ-0q00wHlc1U0xlbyMp9izeXB2FpLMgQ%5B1%5D.jpg" width=240 border=0 mce_src="http://blogs.msdn.com/blogfiles/rick_schaut/WindowsLiveWriter/ThereComesaTime_10853/x1pXjQifqRFQ7oxMft2jDMrP9HH8Kqo184YJQf544Mm9SSDVMW8Z9R0BXcQfqgcJGQzuG5OTcWCwEsoCavOFSCufuZ-0q00wHlc1U0xlbyMp9izeXB2FpLMgQ%5B1%5D.jpg"&gt;&lt;/A&gt; &lt;A href="http://blogs.msdn.com/blogfiles/rick_schaut/WindowsLiveWriter/ThereComesaTime_10853/x1pXjQifqRFQ7oxMft2jDMrP9EYWH2HE395YyKpsTeM_VqZhLgrE5Zb4KJaq_PZeYyuWrVw4tnVKNxfyqIV_BlnsvAVtKwTIUIn3qRJdPvIMLU9iS_fdBqbSg%5B1%5D%5B1%5D.jpg" atomicselection="true" mce_href="http://blogs.msdn.com/blogfiles/rick_schaut/WindowsLiveWriter/ThereComesaTime_10853/x1pXjQifqRFQ7oxMft2jDMrP9EYWH2HE395YyKpsTeM_VqZhLgrE5Zb4KJaq_PZeYyuWrVw4tnVKNxfyqIV_BlnsvAVtKwTIUIn3qRJdPvIMLU9iS_fdBqbSg%5B1%5D%5B1%5D.jpg"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=192 src="http://blogs.msdn.com/blogfiles/rick_schaut/WindowsLiveWriter/ThereComesaTime_10853/x1pXjQifqRFQ7oxMft2jDMrP9EYWH2HE395YyKpsTeM_VqZhLgrE5Zb4KJaq_PZeYyuWrVw4tnVKNxfyqIV_BlnsvAVtKwTIUIn3qRJdPvIMLU9iS_fdBqbSg%5B1%5D.jpg" width=240 border=0 mce_src="http://blogs.msdn.com/blogfiles/rick_schaut/WindowsLiveWriter/ThereComesaTime_10853/x1pXjQifqRFQ7oxMft2jDMrP9EYWH2HE395YyKpsTeM_VqZhLgrE5Zb4KJaq_PZeYyuWrVw4tnVKNxfyqIV_BlnsvAVtKwTIUIn3qRJdPvIMLU9iS_fdBqbSg%5B1%5D.jpg"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;Mind you, this suggestion box is for PGM use only.&amp;nbsp; Think of it as my way of saying that now is the time&amp;nbsp;for us&amp;nbsp;to shut up and listen to the real users who are trying out the product during the private beta.&lt;/P&gt;
&lt;P&gt;Enough fun.&amp;nbsp; I need to get back to fixing bugs.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Rick&lt;/P&gt;
&lt;P&gt;Currently playing in iTunes: &lt;EM&gt;Beautifully Broken&lt;/EM&gt; by Gov't Mule (w/ George Porter Jr.)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2028545" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/rick_schaut/archive/tags/Programming/default.aspx">Programming</category><category domain="http://blogs.msdn.com/rick_schaut/archive/tags/Mac+BU/default.aspx">Mac BU</category></item><item><title>BBEdit 8.5</title><link>http://blogs.msdn.com/rick_schaut/archive/2006/12/14/bbedit-8-5.aspx</link><pubDate>Fri, 15 Dec 2006 01:14:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1288471</guid><dc:creator>Rick Schaut</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/rick_schaut/comments/1288471.aspx</comments><wfw:commentRss>http://blogs.msdn.com/rick_schaut/commentrss.aspx?PostID=1288471</wfw:commentRss><description>&lt;p&gt;MacWorld has a decent &lt;a href="http://www.macworld.com/2006/12/reviews/bbedit85/" target="_blank" mce_href="http://www.macworld.com/2006/12/reviews/bbedit85/"&gt;review of BBEdit 8.5&lt;/a&gt;, but it fails to mention a new feature that is of particular use to programmers.&lt;/p&gt;&lt;p&gt;One of the features of CodeWarrior that I'd missed was the syntax highlighting that the IDE applied to symbols that were defined within the project.&amp;nbsp; In fact, I hadn't realized just how much I'd come to rely on that feature when writing new code until I started working with BBEdit and XCode.&amp;nbsp; I had a sudden, new-found paranoia about whether or not I'd typed in a symbol name correctly.&lt;/p&gt;&lt;p&gt;Well, if you use ctags in association with BBEdit, BBEdit will apply syntax highlighting to any symbol that's in the tags file that it would use for the "Find Definition" command on the Search menu.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Rick&lt;/p&gt;&lt;p&gt;Currently playing in iTunes: &lt;i&gt;The Rainy Season&lt;/i&gt; by Marc Cohn&amp;nbsp;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1288471" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/rick_schaut/archive/tags/Programming/default.aspx">Programming</category><category domain="http://blogs.msdn.com/rick_schaut/archive/tags/Other/default.aspx">Other</category></item><item><title>What's Wrong with this Code: The Answer</title><link>http://blogs.msdn.com/rick_schaut/archive/2006/06/14/630976.aspx</link><pubDate>Wed, 14 Jun 2006 18:21:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:630976</guid><dc:creator>Rick Schaut</dc:creator><slash:comments>10</slash:comments><comments>http://blogs.msdn.com/rick_schaut/comments/630976.aspx</comments><wfw:commentRss>http://blogs.msdn.com/rick_schaut/commentrss.aspx?PostID=630976</wfw:commentRss><description>&lt;P&gt;Bjarne Stroustrup is a brilliant man, which means he's very good at defining programming languages. It also means he's not very good at writing books about the programming languages he's defined. His writing goal is concise precision. Unfortunately, for those of us who have to read what he writes, that quest for concise precision often translates into some of the driest reading in existence.&lt;/P&gt;
&lt;P&gt;Yesterday, I asked &lt;A href="http://blogs.msdn.com/rick_schaut/archive/2006/06/13/629904.aspx"&gt;What's Wrong with this Code&lt;/A&gt;? Unfortunately, the answer to that question involves one of the driest sentences in Stroustrup's book on C++. In fact, it's the very first sentence of section 6.2.2 of &lt;I&gt;The C++ Programming Language&lt;/I&gt;:&lt;/P&gt;
&lt;P&gt;
&lt;BLOCKQUOTE&gt;&lt;I&gt;The order of evaluation of subexpressions within an expression is undefined.&lt;/I&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;Even as I write this, I can hear the collective, "Huh?" So, let's take at look at the key line of code in yesterday's example. It's in the function, &lt;CODE&gt;Foo()&lt;/CODE&gt;:&lt;/P&gt;
&lt;P&gt;
&lt;BLOCKQUOTE&gt;&lt;CODE&gt;_val += Bar(val);&lt;/CODE&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;This is an expression with subexpressions. It's a contractional form of the expression:&lt;/P&gt;
&lt;P&gt;
&lt;BLOCKQUOTE&gt;&lt;CODE&gt;_val = _val + Bar(val);&lt;/CODE&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;It's rather like the contraction "it's"--a way of saying "it is" using fewer letters and syllables. The subexpressions are the bits on either side of the &lt;CODE&gt;+&lt;/CODE&gt; sign and the &lt;CODE&gt;=&lt;/CODE&gt; sign.&lt;/P&gt;
&lt;P&gt;Now, I'd like to translate that expression back into English for you, but I can't. At least I can't give you a definitive translation. The expression is ambiguous. We can read it as:&lt;/P&gt;
&lt;P&gt;
&lt;BLOCKQUOTE&gt;Evaluate the function, &lt;CODE&gt;Bar(val)&lt;/CODE&gt;, add the result to the value in &lt;CODE&gt;_val&lt;/CODE&gt;, and place the sum back into &lt;CODE&gt;_val&lt;/CODE&gt;.&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;Or, we can read it as:&lt;/P&gt;
&lt;P&gt;
&lt;BLOCKQUOTE&gt;Take the value that's in &lt;CODE&gt;_val&lt;/CODE&gt;, add it to the result of the function, &lt;CODE&gt;Bar(val)&lt;/CODE&gt;, and place the sum back into &lt;CODE&gt;_val&lt;/CODE&gt;.&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;Thing is, the actual result of the code example I gave will be different depending upon which interpretation we use. That's because &lt;CODE&gt;Bar()&lt;/CODE&gt; changes &lt;CODE&gt;_val&lt;/CODE&gt; (programmers call this a subexpression side-effect). If we choose the first interpretation, then the result of yesterday's program will leave &lt;CODE&gt;_val&lt;/CODE&gt; with a value of &lt;CODE&gt;2&lt;/CODE&gt;. If we take the second interpretation, then the result of that code will leave &lt;CODE&gt;_val&lt;/CODE&gt; with the value of &lt;CODE&gt;43&lt;/CODE&gt;.&lt;/P&gt;
&lt;P&gt;Well, that's fine, Rick, but what does this have to do with what Stroustrup said? Stroustrup is saying that compiler writers are free to choose either of these interpretations that I've given above. In fact, compiler writers are free to choose one interpretation at one line of code, and another interpretation in a different instance of the same line of code. While this sometimes happens, compiler writers tend to choose one interpretation and stick to it.&lt;/P&gt;
&lt;P&gt;And that's where the real problem lies. Remember, this is a contrived example. Given this kind of contrived coding example, most programmers worth half their paychecks can spot the problem a mile away. But, real-world software models real-world problems. And, real-world problems are complex. So, in the real world, someone writes &lt;CODE&gt;Bar()&lt;/CODE&gt; without the line of code that modifies &lt;CODE&gt;_val&lt;/CODE&gt;. Some time later, someone else adds &lt;CODE&gt;Foo()&lt;/CODE&gt; which uses the computation done in &lt;CODE&gt;Bar()&lt;/CODE&gt;. A little time after that, someone changes &lt;CODE&gt;Bar()&lt;/CODE&gt; so that it now modifies &lt;CODE&gt;_val&lt;/CODE&gt;.&lt;/P&gt;
&lt;P&gt;All of these changes get checked into the code base, built into the product, and tested. They might even get tested over and over again. We might even ship several versions of the product, without ever running into any problem that any user will see. And, so long as the compiler we're using takes the "correct" interpretation, there won't be any problem in the code that we actually ship.&lt;/P&gt;
&lt;P&gt;Then someone comes along and forces us to start using a new compiler, like when Apple announced the move to Intel processors. Should the new compiler interpret these expressions differently than the way the old compiler interprets these expressions, then we'll have a few subtle bugs in our code.&lt;/P&gt;
&lt;P&gt;Now, I've read articles where people describe this programming style as "Microsoft's patchwork programming style," or some such similar--as if the word "patchwork" accurately describes incremental development with modular programming and as if Microsoft is the only entity in existence that uses these programming techniques. Actually, everyone does it this way, and any group engaged in trying to write programs to solve complex problems will end up with some code like this in their products. It's inevitable. I'm quite certain that Adobe has encountered a handful of these kinds of issues in their code, and I'll bet that Apple had to deal with a few of them as well.&lt;/P&gt;
&lt;P&gt;Worse yet, in all of the compiler errors and warnings that &lt;A href="http://www.schwieb.com/blog/2006/06/01/whither-xcode/"&gt;Erik Schwiebert mentioned&lt;/A&gt; in the post that prompted me to offer this little programming example, not one of them involved problems of this type. Those of you who have XCode installed on your machines, copy and paste the code from my example into a test file, and compile it using GCC with every warning you can think of turned on. You'll get nary a peep out of GCC.&lt;/P&gt;
&lt;P&gt;We know that many people are anxiously awaiting universal binaries for Office and Adobe's products. Please, be patient. You really do want us to find all of these subtle issues before we ship these products to you, and that takes time--mostly testing time even when you have a lab like &lt;A href="http://davidweiss.blogspot.com/2006/04/tour-of-microsofts-mac-lab.html#links"&gt;this one&lt;/A&gt; where you can run those tests.&lt;/P&gt;
&lt;P&gt;Kudos to Doug for being the first to say where the problem lies, and kudos to Joshua Ochs for being the first to quote the correct section number from Stroustrup. And, Joshua's guess was almost correct. CodeWarrior uses the first interpretation above. GCC uses the second.&lt;/P&gt;
&lt;P&gt;&lt;B&gt;Update:&lt;/B&gt; Upon reflection, I thought it worth adding, for some of the more experienced programmers out there, some further details that indicate just how insidious this can be. Imagine some code that began its life as Java. Later, it got ported to C++. The key part of the body of &lt;CODE&gt;Foo()&lt;/CODE&gt; is a tight loop that terminates when &lt;CODE&gt;_val&lt;/CODE&gt; reaches 0, and &lt;CODE&gt;Bar()&lt;/CODE&gt; is really invoked through a pointer to member function in an array of pointers to member functions indexed by &lt;CODE&gt;_val&lt;/CODE&gt;. This is the kind of stuff that keeps me awake at night.&lt;/P&gt;
&lt;P&gt; &lt;/P&gt;
&lt;P&gt;Rick&lt;/P&gt;
&lt;P&gt;Currently playing in iTunes: &lt;I&gt;Everyday (I Have the Blues)&lt;/I&gt; by The Marshall Tucker Band&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=630976" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/rick_schaut/archive/tags/Programming/default.aspx">Programming</category><category domain="http://blogs.msdn.com/rick_schaut/archive/tags/Mac+BU/default.aspx">Mac BU</category></item><item><title>What's Wrong with this Code?</title><link>http://blogs.msdn.com/rick_schaut/archive/2006/06/13/629904.aspx</link><pubDate>Tue, 13 Jun 2006 22:44:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:629904</guid><dc:creator>Rick Schaut</dc:creator><slash:comments>21</slash:comments><comments>http://blogs.msdn.com/rick_schaut/comments/629904.aspx</comments><wfw:commentRss>http://blogs.msdn.com/rick_schaut/commentrss.aspx?PostID=629904</wfw:commentRss><description>&lt;P&gt;A while back, Erik Schwiebert wrote about some of the &lt;A href="http://www.schwieb.com/blog/2006/06/01/whither-xcode/"&gt;travails of moving our build system&lt;/A&gt; from one using CodeWarrior to one using XCode and GCC. Erik mentioned the huge number of errors and warnings we've had to resolve, but, in reading some of the reactions around the web, I'm afraid that some people, particularly people who know nothing about compilers and developing software, seem to have completely mistaken Erik's remarks. &lt;/P&gt;
&lt;P&gt;Someday, I'll understand why people are motivated to render opinions on matters of which they are entirely ignorant, but, for now, I'll have to satisfy myself by offering some remedial education. I'll start by asking, what's wrong with the following code: &lt;/P&gt;
&lt;P&gt;&lt;PRE&gt;&lt;CODE&gt;
&lt;FONT color=#0000ff&gt;class&lt;/FONT&gt; FooBar
{
&lt;FONT color=#0000ff&gt;public&lt;/FONT&gt;:
    FooBar(&lt;FONT color=#0000ff&gt;int&lt;/FONT&gt; val): _val(val) {};
    ~FooBar() {};

    &lt;FONT color=#0000ff&gt;void&lt;/FONT&gt; Foo(&lt;FONT color=#0000ff&gt;int&lt;/FONT&gt; val)
        {
        _val += Bar(val);
        };

    &lt;FONT color=#0000ff&gt;int&lt;/FONT&gt; Val() { &lt;FONT color=#0000ff&gt;return&lt;/FONT&gt; _val; };

&lt;FONT color=#0000ff&gt;private&lt;/FONT&gt;:
    int Bar(&lt;FONT color=#0000ff&gt;int&lt;/FONT&gt; val)
        {
        _val = val;
        &lt;FONT color=#0000ff&gt;return&lt;/FONT&gt; _val;
        };

    &lt;FONT color=#0000ff&gt;int&lt;/FONT&gt; _val;
};

&lt;FONT color=#0000ff&gt;int&lt;/FONT&gt; main()
{
    FooBar fb(42);
    fb.Foo(1);

    int val = fb.Val();

    &lt;FONT color=#0000ff&gt;return&lt;/FONT&gt; 0;
}&lt;/CODE&gt;
&lt;/PRE&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;Some of my readers will spot the problem immediately. To those who do, I'll remind you that this is a contrived example. A real-world example will have a class that has 10 or more methods, and none of those methods will be as trivial as Foo or Bar.&lt;/P&gt;
&lt;P&gt;&lt;strong&gt;Update:&lt;/strong&gt; Fixed code problems due to .Text's handling of HTML entities.&lt;/P&gt;
&lt;P&gt; &lt;/P&gt;
&lt;P&gt;Rick&lt;/P&gt;
&lt;P&gt;Currently playing in iTunes: &lt;I&gt;One Way Out&lt;/I&gt; by The Allman Brothers&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=629904" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/rick_schaut/archive/tags/Programming/default.aspx">Programming</category><category domain="http://blogs.msdn.com/rick_schaut/archive/tags/Mac+BU/default.aspx">Mac BU</category></item><item><title>Compound Statement Macros</title><link>http://blogs.msdn.com/rick_schaut/archive/2005/08/31/458841.aspx</link><pubDate>Thu, 01 Sep 2005 03:57:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:458841</guid><dc:creator>Rick Schaut</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/rick_schaut/comments/458841.aspx</comments><wfw:commentRss>http://blogs.msdn.com/rick_schaut/commentrss.aspx?PostID=458841</wfw:commentRss><description>I had thought this was a rather well-known trick, but, after reacquanting myself with Alexandrescu's Modern C++ Design , I've come to believe that it's not at as well-known as I thought. So, I thought I'd share it here for posterity. It's common to write...(&lt;a href="http://blogs.msdn.com/rick_schaut/archive/2005/08/31/458841.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=458841" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/rick_schaut/archive/tags/Programming/default.aspx">Programming</category></item><item><title>Got Frontier and MacBird Experience?</title><link>http://blogs.msdn.com/rick_schaut/archive/2005/06/15/429335.aspx</link><pubDate>Wed, 15 Jun 2005 17:52:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:429335</guid><dc:creator>Rick Schaut</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/rick_schaut/comments/429335.aspx</comments><wfw:commentRss>http://blogs.msdn.com/rick_schaut/commentrss.aspx?PostID=429335</wfw:commentRss><description>&lt;p&gt;Dave Winer is &lt;a href="http://archive.scripting.com/2005/06/15#reallySimpleGroupware"&gt;looking for a Mac developer&lt;/a&gt; with knowledge of &lt;a href="http://frontier.userland.com/"&gt;Frontier&lt;/a&gt; and &lt;a href="http://macbird.userland.com/"&gt;MacBird&lt;/a&gt; to work on his latest project: an OPML editor.  According to Dave, the Mac version is stalled.&lt;/p&gt;

&lt;p&gt;If I didn't just get a &lt;a href="http://blogs.msdn.com/rick_schaut/archive/2005/06/07/426443.aspx"&gt;load of work&lt;/a&gt; heaped on me, I'd be sorely tempted to toss my hat in.  It'd be a great, and really fun, chance to work with Dave Luebbert again.&lt;/p&gt;

&lt;p&gt;At one point in my life, I aspired to be a guitar player.  I still play guitar, but my day gig is just too good to give up.  Back in those early days, however, I absorbed as much as I could.  I still have a dog-eared copy of the late Tommy Tedesco's &lt;i&gt;For Guitar Players Only&lt;/i&gt;.&lt;/p&gt;

&lt;p&gt;Tommy gave a lot of great advice in that book, and one of the best is that there are really only three reasons to ever take a gig: you'll make money from it, you'll learn from it or you'll just plain have fun doing it.  Winer's gig looks like it has two out of those three.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Rick&lt;/p&gt;
&lt;p&gt;Currently playing in iTunes: &lt;i&gt;The Life&lt;/i&gt; by Alicia Keys&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=429335" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/rick_schaut/archive/tags/Programming/default.aspx">Programming</category><category domain="http://blogs.msdn.com/rick_schaut/archive/tags/Other/default.aspx">Other</category></item><item><title>Flipping Out</title><link>http://blogs.msdn.com/rick_schaut/archive/2005/06/07/426443.aspx</link><pubDate>Wed, 08 Jun 2005 01:12:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:426443</guid><dc:creator>Rick Schaut</dc:creator><slash:comments>12</slash:comments><comments>http://blogs.msdn.com/rick_schaut/comments/426443.aspx</comments><wfw:commentRss>http://blogs.msdn.com/rick_schaut/commentrss.aspx?PostID=426443</wfw:commentRss><description>&lt;p&gt;I've seen quite a few people comment in blogs that the &lt;a href="http://blogs.msdn.com/rick_schaut/archive/2005/06/07/425990.aspx"&gt;endian issue&lt;/a&gt; I mentioned yesterday won't turn out to be much of an issue.  Well, you can't say I didn't warn you about drinking the Kool-Aid, but it you still have some lingering doubts that there isn't a significant number of developers out there who are going to have issues, go wade your way through &lt;a href="http://developer.apple.com/documentation/MacOSX/Conceptual/universal_binary/universal_binary_byte_swap/chapter_4_section_1.html#//apple_ref/doc/uid/TP40002217-CH243"&gt;this stuff&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For a more concrete example, Apple have produced documentation for developers who use PowerPlant.  PowerPlant uses various resources to describe the UI objects that are created--windows, menus, dialog boxes, etc.  Reading these resources correctly in the context of a universal binary will be crucial.  They've included some &lt;a href="http://developer.apple.com/documentation/MacOSX/Conceptual/universal_binary/universal_binary_ppob_a/chapter_11_section_1.html#//apple_ref/doc/uid/TP40002217-CH241"&gt;sample code&lt;/a&gt; to flip bytes in PowerPlant resources.  It's more than 780 lines of code--780 lines of tedious, byte flipping code.&lt;/p&gt;

&lt;p&gt;Now, there are quite a few people who are likely to say that this is really just an extreme example of where byte-swapping is problematic; that, if developers followed all the "rules" they will have no problem.  The fact is that these "rules" are nothing more than rules-of-thumb--general guidelines that many developers will disregard for very legitimate reasons.&lt;/p&gt;

&lt;p&gt;Consider a drawing program like Adobe Illustrator (I almost said FreeHand--does that date me?).  Undo is an important feature in a drawing program.  There are two ways to do Undo: save off an entire copy of an object for each user action, or encode user actions as operation codes that can be transacted.  In the latter case, you save the object in its original state plus all of the changes the user made to the object as opcodes.  Chances are that the opcode solution will result in much smaller files.  It does, however, break the "rules" that unknowing people tend to tout when these kinds of discussions arise.&lt;/p&gt;

&lt;p&gt;No.  The PowerPlant resource example isn't extreme.  It's just a common, specific example for which Apple have been kind enough to provide a solution.  Anyone shipping serious applications that have not already had to solve this problem for cross-platform scenarios has quite a bit of tedious work to do.  While I've welcomed this change for my own circumstances, I don't envy the position in which a number of my compatriots down in San Jose find themselves.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Rick&lt;/p&gt;
&lt;p&gt;Currently playing in iTunes: &lt;i&gt;If 6 Was 9&lt;/i&gt; by Jimi Hendrix&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=426443" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/rick_schaut/archive/tags/Programming/default.aspx">Programming</category><category domain="http://blogs.msdn.com/rick_schaut/archive/tags/Other/default.aspx">Other</category></item><item><title>The Beginning of the Endian</title><link>http://blogs.msdn.com/rick_schaut/archive/2005/06/07/425990.aspx</link><pubDate>Tue, 07 Jun 2005 11:04:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:425990</guid><dc:creator>Rick Schaut</dc:creator><slash:comments>21</slash:comments><comments>http://blogs.msdn.com/rick_schaut/comments/425990.aspx</comments><wfw:commentRss>http://blogs.msdn.com/rick_schaut/commentrss.aspx?PostID=425990</wfw:commentRss><description>&lt;p&gt;So the rumors have been true.  Apple is moving to Intel processors, which, in some ways, makes sense.  At least it does from Apple's point of view.  The Kool-Aid has never really affected their ability to figure out what's right for Apple regardless of the direction they've taken.&lt;/p&gt;

&lt;p&gt;For users, the transition won't be all that painful either.  Indeed, the prospect of being able to run VirtualPC on a native Intel processor has me, as a user, licking my chops.  Buy a Mac and you'll get the best of all three worlds: Mac, Unix and Windows.&lt;/p&gt;

&lt;p&gt;When you're a developer, though, the Kool-Aid can be rather heady.  For those of us who've been around for a while, developing software for Apple's computers has often been rather like being a farm animal with a ring through its nose.  In fact, the primary difference between Apple and Microsoft as platform vendors is that Apple generates excitement in the user base while Microsoft tends toward generating excitement in the independent software developer base.&lt;/p&gt;

&lt;p&gt;So, when Steve Jobs starts talking about certain software developers having little trouble making the transition from the PowerPC to x86 processors, you can pretty well bet that the Kool-Aid is laced with all sorts of compounds that are not there for your benefit.&lt;/p&gt;

&lt;p&gt;No doubt, some, perhaps even many, applications will have little difficulty making the transition.  There is, however, a class of applications that will require a significant amount of work.  The feature they all have in common: they produce documents--files with data in binary form.  To understand why, we need a little lesson in the history of microprocessor design.&lt;/p&gt;

&lt;p&gt;Microprocessors have data registers.  These are analogous to little scratch-pads on your desktop.  When the computer needs to do some manipulation of data, it pulls that data out of memory and puts it into these little scratch pads.  When the computer is done with that data, yet wants to save it for later use, it writes the data on the scratch pad out to memory.&lt;/p&gt;

&lt;p&gt;Early microprocessors had 8-bit, or byte-sized, data registers.  This was generally convenient, because memory is considered to be just a very huge array of bytes.  However, when the first 16-bit microprocessors were designed, the size of the scratch pads, or data registers, was twice the size of a single, addressable piece of memory.&lt;/p&gt;

&lt;p&gt;This introduced a design problem.  When you read a 16-bit value from a byte-addressable data store, like memory, which byte do you load first?  You have two choices.  You can load the most-significant byte first (known as big-endian), or you can load the least-significant byte first (known as little-endian).  The difference between big-endian and little-endian systems is often referred to as "byte-sex".  It's a term I've used before, and, for those who've wondered what it means, now you know.&lt;/p&gt;

&lt;p&gt;As luck would have it, the two most active designers of microprocessors at the time, Intel and Motorola, answered that question in opposite ways.  I'm not well-versed in VLSI design, but I have little doubt that each group of chip designers had legitimate reasons for the choices they made.  None of that is important here.  What is important is that, way back in those days, Apple chose Motorola processors while IBM chose Intel.  Thus began the great endian divide.&lt;/p&gt;

&lt;p&gt;Independent of each other, this isn't really a significant issue.  Big-endian is slightly more difficult to work with than little-endian, but the parameter type provided by modern compilers renders the problem negligible.  The real problem starts when binary data gets saved to disk and shared.&lt;/p&gt;

&lt;p&gt;To see how this works, imagine a program that keeps track of people's salaries.  Your boss decides to give you a raise, so this program reads your salary from memory into one of these data registers, adds your raise to it, and then writes it back out to memory.  At the end of the day, the program stores all employee records to disk as just an array of bytes as they reside in memory.  Let's also pretend that the accounts use computers with Intel processors, so the data got written in little-endian format.&lt;/p&gt;

&lt;p&gt;Now suppose you want to look to make sure you got the correct raise.  You fire up a program on your Mac that reads your employee record, but when it reads your salary, it's going to read the bytes of that number in reverse order from the way it was written on an Intel processor.  If your new salary is supposed to be $128 a week, unless the data was byte-swapped when it was read from the disk, your Mac will lead you to believe that your salary is really $2,147,483,648 per week.  Now &lt;i&gt;that's&lt;/i&gt; a raise!&lt;/p&gt;

&lt;p&gt;If you think this is messy, then know that I've oversimplified the problem significantly.  Rarely do programs maintain various numbers in isolation from each other.  Employee records often have other numbers associated with them, like hours, hire dates, number of children, exemption status, etc.  These are kept in compound data structures generally known as records.  Many of them are quite huge.&lt;/p&gt;

&lt;p&gt;When transferring data between x86 and PowerPC based computers, each numeric value in each of these records needs to be byte-swapped.  Code that doesn't properly byte-swap data written on the other processor type has a bug.  I call these "unsafe byte-sex" bugs.  If you're going to move documents with binary data between PowerPC and Intel processors, you have to write code that practices safe byte-sex.&lt;/p&gt;

&lt;p&gt;For some developers, this problem will be huge.  Word, for example, has a total of 176 distinct data structures in its binary file format, each of which needs to be properly byte-swapped whenever one of them is read from the disk.  Word's example is probably a bit extreme, but even 20 or 30 data structures requiring proper byte-swapping represents a good chunk of work for both developers and testers.&lt;/p&gt;

&lt;p&gt;That said, life for Word will actually get quite a bit easier.  Why?  Because Word's files are always written in Intel byte-sex.  Given the number of unsafe byte-sex bugs I've had to fix over the course of my career working on Word, I'm actually looking forward to the day when I can forget about them almost entirely.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Rick&lt;/p&gt;
&lt;p&gt;Currently playing in iTunes: &lt;i&gt;Saint Augustine In Hell&lt;/i&gt; by Sting&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=425990" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/rick_schaut/archive/tags/Programming/default.aspx">Programming</category><category domain="http://blogs.msdn.com/rick_schaut/archive/tags/Microsoft+Word/default.aspx">Microsoft Word</category><category domain="http://blogs.msdn.com/rick_schaut/archive/tags/Mac+BU/default.aspx">Mac BU</category></item><item><title>C++ Function Objects</title><link>http://blogs.msdn.com/rick_schaut/archive/2005/05/15/417614.aspx</link><pubDate>Sun, 15 May 2005 20:01:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:417614</guid><dc:creator>Rick Schaut</dc:creator><slash:comments>12</slash:comments><comments>http://blogs.msdn.com/rick_schaut/comments/417614.aspx</comments><wfw:commentRss>http://blogs.msdn.com/rick_schaut/commentrss.aspx?PostID=417614</wfw:commentRss><description>&lt;p&gt;
&lt;p&gt;C++ provides us with a number of ways we can shoot ourselves in the foot. If
you work as a developer on any sizeable software project, there is quite likely
a set of rules about limitations as to the C++ language features you’re allowed
to use: no memory allocation in constructors, no operator overloading,
exceptions used only for error handling, etc. Repentance for violating these
rules often resembles that for breaking the master build—i.e. some
obligation to perform some menial yet necessary task for the group and/or the
possession of some object of indistinction (“The Hat” or “The Hose”).&lt;/p&gt;
&lt;/p&gt;

&lt;p&gt;
&lt;p&gt;There are, however, reasons for flexibility where at least some of these
rules are concerned, and I’ll offer as an example some practical considerations
in favor of allowing the use of operator overloading for &lt;code&gt;operator()&lt;/code&gt; (that’s read as “function-call
operator”). If you happen to be one of the lucky ones who work on projects with
only one or two other programmers, or even just by yourself, stick around.
‘Cause function objects are cool, and I’m about to tell you why.&lt;/p&gt;
&lt;/p&gt;

&lt;p&gt;
&lt;p&gt;Those of us who write software for the Macintosh know that the world is really
divided into three: Windows, Macintosh and Unix. How do we know this? Because
we’re constantly having to manipulate the line endings of various text files.
Curiously enough, the standard Mac OS X install doesn’t have a neat little
command-line tool for converting line endings (or at least “apropos” with
various forms of the phrase “convert line endings” yields “nothing
appropriate”). There isn’t even one among the little more than two dozen
command line tools in Apple’s Developer Tools.&lt;/p&gt;
&lt;/p&gt;

&lt;p&gt;
&lt;p&gt;So, if you often find yourself having to flip the line endings of various
text files, you’ll either open them all up in, say, XCode or BBEdit, and
manipulate the line endings by hand, or you’ll write a little command line tool
that will do what you need. The benefit of the latter is that it can handle
large numbers of files all at once.&lt;/p&gt;
&lt;/p&gt;

&lt;p&gt;
&lt;p&gt;Should you write one such tool, you’re quite likely to have three different
functions in your code that look something like this:&lt;/p&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/*----------------------------------------------------------------------------&lt;br&gt;
    %%Function: ClnConvertToWin&lt;br&gt;
    %%Contact: richs&lt;br&gt;
----------------------------------------------------------------------------*/&lt;br&gt;
int ClnConvertToWin(InputFile &amp;in, OutputFile &amp;out)&lt;br&gt;
{&lt;br&gt;
    char chPrev = chNul;&lt;br&gt;
    int cln = 0;&lt;br&gt;
&lt;br&gt;
    for (;;)&lt;br&gt;
        {&lt;br&gt;
        int ch = in.ChGet()&lt;br&gt;
        &lt;br&gt;
        if (in.FEof())&lt;br&gt;
            break;&lt;br&gt;
        &lt;br&gt;
        switch(ch)&lt;br&gt;
            {&lt;br&gt;
        default:&lt;br&gt;
            out.PutChar(ch);&lt;br&gt;
            break;&lt;br&gt;
&lt;br&gt;
        case chCR:&lt;br&gt;
            out.PutChar(ch);&lt;br&gt;
&lt;br&gt;
            if (chLF != in.ChPeek())&lt;br&gt;
                {&lt;br&gt;
                out.PutChar(chLF);&lt;br&gt;
                cln++;&lt;br&gt;
                }&lt;br&gt;
            break;&lt;br&gt;
&lt;br&gt;
        case chLF:&lt;br&gt;
            if (chPrev != chCR)&lt;br&gt;
                {&lt;br&gt;
                cln++;&lt;br&gt;
                out.PutChar(chCR);&lt;br&gt;
                }&lt;br&gt;
            out.PutChar(ch);&lt;br&gt;
            break;&lt;br&gt;
            }&lt;br&gt;
        chPrev = ch;&lt;br&gt;
        }&lt;br&gt;
&lt;br&gt;
    return cln;&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;
&lt;p&gt;This code, which converts an arbitrary input file to Windows’ line endings,
looks simple enough. It reads a character from the input file one character at
a time, and performs some specific action based on which character is just
read. It keeps track of the number of lines that it’s converted, and returns
that count when it’s all done.&lt;/p&gt;
&lt;/p&gt;

&lt;p&gt;
&lt;p&gt;The two other versions of this function likely have the exact same loop
control and differ only by the structure of the &lt;code&gt;switch&lt;/code&gt; statement that does the actual conversion of line
endings.&lt;/p&gt;
&lt;/p&gt;

&lt;p&gt;
&lt;p&gt;This is bad, because you now have three separate loops in your code that are
almost identical. Suppose, for example, that you move this code to a system
where the “read a character, then test for end-of-file” construct isn’t the
most efficient or robust way to read characters from a file. You now have three
separate loops of code to change, and three separate opportunities to create
bugs in the code.&lt;/p&gt;
&lt;/p&gt;

&lt;p&gt;
&lt;p&gt;In the old days, we might have resolved this problem by using function
pointers, but they’re clumsy. Also, function pointers provide no opportunity
for the compiler to optimize out the function-call semantics. You’re going to
be stuck with full procedure prologue and epilogue with every iteration through
that loop. For performance reasons, as well as maintenance reasons, we don’t
want to use function pointers in this particular application.&lt;/p&gt;
&lt;/p&gt;

&lt;p&gt;
&lt;p&gt; With C++, however, we can encapsulate the &lt;code&gt;switch&lt;/code&gt; statement into a function
object, and put the control loop in a template function that takes as a
parameter a reference to an object that overloads &lt;code&gt;operator()&lt;/code&gt;.
The template that encapsulates the loop might look like:&lt;/p&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/*----------------------------------------------------------------------------&lt;br&gt;
    %%Function: ClnConvertLines&lt;br&gt;
    %%Contact: richs&lt;br&gt;
    &lt;br&gt;
----------------------------------------------------------------------------*/&lt;br&gt;
template &amp;lt;class CharConverter&amp;gt;&lt;br&gt;
int ClnConvertLines(InputFile &amp;in,
CharConverter &amp;cnv)&lt;br&gt;
{&lt;br&gt;
    int cln = 0;&lt;br&gt;
    for (;;)&lt;br&gt;
        {&lt;br&gt;
        int ch = in.ChGet();&lt;br&gt;
        &lt;br&gt;
        if (in.FEof())&lt;br&gt;
            break;&lt;br&gt;
&lt;br&gt;
        cnv(ch, cln);&lt;br&gt;
        }&lt;br&gt;
    &lt;br&gt;
    return cln;&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;
&lt;p&gt;And the function object that converts arbitrary line endings to Windows
might look like:&lt;/p&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/*----------------------------------------------------------------------------&lt;br&gt;
    %%Class: ToWin&lt;br&gt;
    %%Contact: richs&lt;br&gt;
----------------------------------------------------------------------------*/&lt;br&gt;
class ToWin&lt;br&gt;
{&lt;br&gt;
public:&lt;br&gt;
    ToWin(InputFile
&amp;anIn, OutputFile &amp;anOut) :&lt;br&gt;
            in(anIn),&lt;br&gt;
            out(anOut),&lt;br&gt;
            chPrev(chNul) {};&lt;br&gt;
    ~ToWin() {};&lt;br&gt;
    void operator()(int ch,
int &amp;cln)&lt;br&gt;
        {&lt;br&gt;
        switch(ch)&lt;br&gt;
            {&lt;br&gt;
        default:&lt;br&gt;
            out.PutChar(ch);&lt;br&gt;
            break;&lt;br&gt;
&lt;br&gt;
        case chCR:&lt;br&gt;
            out.PutChar(ch);&lt;br&gt;
            if (chLF != in.ChPeek())&lt;br&gt;
                {&lt;br&gt;
                out.PutChar(chLF);&lt;br&gt;
                cln++;&lt;br&gt;
                }&lt;br&gt;
            break;&lt;br&gt;
&lt;br&gt;
        case chLF:&lt;br&gt;
            if (chPrev != chCR)&lt;br&gt;
                {&lt;br&gt;
                cln++;&lt;br&gt;
                out.PutChar(chCR);&lt;br&gt;
                }&lt;br&gt;
            out.PutChar(ch);&lt;br&gt;
            break;&lt;br&gt;
            }&lt;br&gt;
        chPrev = ch;&lt;br&gt;
        };&lt;br&gt;
private:&lt;br&gt;
    int chPrev;&lt;br&gt;
    OutputFile &amp;out;&lt;br&gt;
    InputFile &amp;in;&lt;br&gt;
};&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;With that, our original conversion function becomes:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Inline int ClnConvertToWin(InputFile &amp;in, OutputFile &amp;out)&lt;br&gt;
{&lt;br&gt;
    ToWin cnv(in,
out);&lt;br&gt;

    return ClnConvertLines(in,
cnv);&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I should point out that there is no a priori reason for &lt;code&gt;ClnConvertLines&lt;/code&gt; to be a
template. We could have defined a
base class, &lt;code&gt;CharConverter&lt;/code&gt;,
that virtualized &lt;code&gt;operator()&lt;/code&gt;,
and made &lt;code&gt;ToWin&lt;/code&gt; a subclass
of &lt;code&gt;CharConverter&lt;/code&gt;. In this particular case, however, the
virtualized base class approach isn’t any better than the old-style, function
pointer approach. In fact, on some
systems, it’s worse, because you have the double-dereference through an object’s
v-table instead of the single dereference of a function pointer.&lt;/p&gt;

&lt;p&gt;The template-based solution, while it yields more object code in that &lt;code&gt;ClnConvertLines&lt;/code&gt; will get instantiated
for every different flavor of &lt;code&gt;cnv&lt;/code&gt;
object we give it, is much faster for our application. Because the template-based solution
gets expanded in line, there is an opportunity for the compiler to optimize out
the function-call semantics where the overloaded &lt;code&gt;operator()&lt;/code&gt; is invoked—one
of those rare instances where we get to have our cake and eat it too.&lt;/p&gt;

&lt;p&gt;Now, if that weren’t cool enough, the fact that we’ve abstracted out the
actual conversion of line endings into a separate piece of source code leads to
a flexibility one wouldn’t want to entertain in the purely functional
approach. For example, suppose we know that a particular input file has Macintosh line endings. Scanning the beginning of an input file
to figure out the existing line endings isn’t all that hard, and is well worth
the time if it greatly simplifies our inner loop. The implementation of the
line conversion from Macintosh to Windows line endings is almost trivial:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/*----------------------------------------------------------------------------&lt;br&gt;
    %%Class: MacToWin&lt;br&gt;
    %%Contact: richs&lt;br&gt;
----------------------------------------------------------------------------*/&lt;br&gt;
class MacToWin&lt;br&gt;
{&lt;br&gt;
public:&lt;br&gt;
    MacToWin(OutputFile &amp;anOut) :&lt;br&gt;
            out(anOut) {};&lt;br&gt;
    ~MacToWin() {};&lt;br&gt;
    void operator()(int ch,
int &amp;cln)&lt;br&gt;
        {&lt;br&gt;
        out.PutChar(ch);&lt;br&gt;
&lt;br&gt;
        if (ch
== chCR)&lt;br&gt;
            {&lt;br&gt;
            out.PutChar(chLF);&lt;br&gt;
            cln++;&lt;br&gt;
            }&lt;br&gt;
        };&lt;br&gt;
private:&lt;br&gt;
    OutputFile
&amp;out;&lt;br&gt;
};&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You wouldn’t entertain something like this in the purely functional
approach, because the proliferation of code with the same loop semantics is
something you want to avoid. If having just three duplicates of that outer loop
is bad, having one for every possible known combination of input and output
line endings is that much more of a maintenance headache. With function objects, we can proliferate
to our heart’s content without increasing the level of maintenance required
should we decide to change the semantics of the loop control.&lt;/p&gt;

&lt;p&gt;By now, there’s at least one astute reader who’s thinking, “Gosh, Schaut,
flipping line endings isn’t all that different from iterating through one of
the Standard Template Library’s collection classes. Using function objects should be obvious. What’s all the fuss about?”&lt;/p&gt;

&lt;p&gt;Such an astute reader would be absolutely correct: they way I’ve used
function objects here is almost exactly the way function objects are used in
the STL. In fact, we can take that
line of thought and extend it to the concept of an input iterator.&lt;/p&gt;

&lt;p&gt;Think about how one might use a command-line tool to convert line
endings. Some times, you’ll want
to just invoke the tool on a single file.
Other times, you’ll want to invoke the tool on a whole bunch of files in
a single directory. On still other
occasions, you’ll want to use some complex &lt;code&gt;find&lt;/code&gt;
command to generate a list of files in an entire directory tree, and pipe the
output of that command through the line converter’s standard input file.&lt;/p&gt;

&lt;p&gt;So, you’ll have two distinct ways of getting a list of files to convert: as
an array of C-style strings provided on the command line or as a list of file
names coming in via your standard input file. The structure of the loop to convert files and report the
progress of that conversion to the user ought not change simply because we’re
getting a list of files in two distinctly separate ways. This problem screams for a solution
where input iterators are implemented as function objects.&lt;/p&gt;

&lt;p&gt;I’ll leave the actual implementation of this as an exercise for the reader,
but there is one thought to consider.
The input iterator is in an outer loop, not an inner loop, and the
function that figures out which particular conversion loop to invoke is likely
to be complex enough that we wouldn’t want multiple copies of it in our object
code. In this case, I would avoid
a template-based approach in favor of defining a base class for our input
iterators where the &lt;code&gt;operator()&lt;/code&gt;
is virtualized.&lt;/p&gt;

&lt;p&gt;Hopefully, this will lead some of you to think more about using function
objects in your daily work—in particular, I’d want you to think that
function objects are useful outside something as complex as the Standard
Template Library. If function
objects can improve our implementation of something as mundanely simple as
flipping line endings in text files, they just have to be cool enough to use in
a wide variety of contexts.&lt;/p&gt;

&lt;p&gt;  &lt;/p&gt;

&lt;p&gt;Rick Schaut&lt;/p&gt;

&lt;p&gt;Currently playing in iTunes: &lt;i&gt;Sierra Leone&lt;/i&gt; by Derek Trucks Band&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt; Fixed the template definition for ClnConvertLines (convert  to HTML entities).&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=417614" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/rick_schaut/archive/tags/Programming/default.aspx">Programming</category></item><item><title>Subtle Bugs</title><link>http://blogs.msdn.com/rick_schaut/archive/2005/04/10/406986.aspx</link><pubDate>Mon, 11 Apr 2005 05:53:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:406986</guid><dc:creator>Rick Schaut</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/rick_schaut/comments/406986.aspx</comments><wfw:commentRss>http://blogs.msdn.com/rick_schaut/commentrss.aspx?PostID=406986</wfw:commentRss><description>    &lt;p&gt;It wouldn't surprise me for people to wonder how it&amp;rsquo;s possible for reasonably competent programmers to introduce bugs by making seemingly innocuous changes to some program&amp;rsquo;s code. The short answer is that we&amp;rsquo;re often too clever for our own good. We&amp;rsquo;ll employ little tricks that subtly change the semantics of the data that we&amp;rsquo;re manipulating. These small changes in semantics can result in weird bugs.&lt;/p&gt;
    &lt;p&gt;There&amp;rsquo;s a good example of this in the sample code that Apple distributes with the developer tools for Mac OS X. One bit of sample code implements a rudimentary framework for Carbon Human Interface objects. Among this code is the implementation of a wrapper C++ class for Carbon Events. The following is a method implemented in this class. It extracts a &lt;code&gt;Boolean&lt;/code&gt; parameter from a Carbon Event, and returns it in a pointer to a &lt;code&gt;bool&lt;/code&gt;.&lt;/p&gt;
    &lt;p&gt;&lt;code&gt;//-----------------------------------------------------------------------------------&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;//&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetParameter&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;//-----------------------------------------------------------------------------------&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;//&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;OSStatus&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;TCarbonEvent::GetParameter(&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;EventParamName&amp;nbsp;&amp;nbsp;inName,&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bool*&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;outValue )&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;{&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return GetParameter&amp;lt;Boolean&amp;gt;( inName, sizeof( Boolean ), (Boolean*) outValue );&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;}&lt;/code&gt;&lt;/p&gt;
    &lt;p&gt;For my non-programming readers, both a &lt;code&gt;Boolean&lt;/code&gt; and a &lt;code&gt;bool&lt;/code&gt; represent values in Boolean algebra. Boolean algebra is the algebra of logic, and Boolean variables take on only one of two values: &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;. In computing practice, and in the C++ Language, &lt;code&gt;false&lt;/code&gt; is equivalent to 0, and &lt;code&gt;true&lt;/code&gt; is any non-zero value.&lt;/p&gt;
    &lt;p&gt;The problem, however, is that &lt;code&gt;Boolean&lt;/code&gt; and &lt;code&gt;bool&lt;/code&gt; are different language types. &lt;code&gt;Boolean&lt;/code&gt; represents the traditional Macintosh implementation of the concept, while &lt;code&gt;bool&lt;/code&gt; is the concept as specified in the C++ Language standard. &lt;code&gt;Boolean&lt;/code&gt; is type-equivalent to an &lt;code&gt;unsigned&lt;/code&gt; &lt;code&gt;char&lt;/code&gt;&amp;mdash;a single-byte quantity, while the underlying implementation of &lt;code&gt;bool&lt;/code&gt; can change from one compiler to the next. In Metrowerks, for example, &lt;code&gt;bool&lt;/code&gt; is usually type equivalent to an &lt;code&gt;unsigned&lt;/code&gt; &lt;code&gt;int&lt;/code&gt;&amp;mdash;a four-byte quantity.&lt;/p&gt;
    &lt;p&gt;And therein lies the problem. The code above blandly takes a pointer to a four-byte quantity and passes it to a piece of code that expects a pointer to a single-byte quantity. This would not be a problem on Intel processors, but the PowerPC is big endian. On a big endian system, when you take the address of a four-byte quantity the resulting pointer actually points to the highest-order byte (i.e. the &amp;ldquo;big&amp;rdquo; end of the four-byte quantity) rather than the lowest-order byte (i.e. the &amp;ldquo;little&amp;rdquo; end of the four-byte quantity).&lt;/p&gt;
    &lt;p&gt;Suppose the called code uses the number 1 as a constant value representing &lt;code&gt;true&lt;/code&gt;. If the requested parameter of the wrapped Carbon event is &lt;code&gt;true&lt;/code&gt;, then this implementation of &lt;code&gt;GetParameter&lt;/code&gt; will put the number 1 in the high-order byte of &lt;code&gt;outValue&lt;/code&gt;. Instead of getting the number 1, then, &lt;code&gt;outValue&lt;/code&gt; actually gets the number 16777216 (or &lt;code&gt;0x1000000&lt;/code&gt; hexadecimal).&lt;/p&gt;
    &lt;p&gt;Now, in terms of language semantics, there&amp;rsquo;s nothing specifically wrong with this notion. Both numbers, 1 and 16777216, being non-zero values are valid representations for &lt;code&gt;true&lt;/code&gt;. However, most compilers favor using the number 1 to represent the actual value for the constant &lt;code&gt;true&lt;/code&gt;, and &amp;ldquo;clever&amp;rdquo; programmers often take advantage of this fact, and will use the result of a Boolean expression in arithmetic expecting a &lt;code&gt;true&lt;/code&gt; result to be the same as the number 1.&lt;/p&gt;
    &lt;p&gt;If some other programmer has written a piece of code that takes advantage of this tendency to use 1 to represent true, the implementation above breaks that code. This is how subtle bugs enter programs: two programmers being &amp;ldquo;clever&amp;rdquo; in mutually exclusive ways.&lt;/p&gt;
    &lt;p&gt;The immediate problem with the above code is that it doesn&amp;rsquo;t make its cleverness explicit. One way to do this is to add a &lt;code&gt;CompileAssert&lt;/code&gt;:&lt;/p&gt;
    &lt;p&gt;&lt;code&gt;#define CompileAssert(_expr) extern int _compile_assert_failed[!!(_expr)]&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;//-----------------------------------------------------------------------------------&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;//&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetParameter&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;//-----------------------------------------------------------------------------------&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;//&lt;/code&gt;&lt;br&gt;&lt;code&gt;OSStatus&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;TCarbonEvent::GetParameter(&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;EventParamName&amp;nbsp;&amp;nbsp;inName,&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bool*&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; outValue )&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;{&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CompileAssert( sizeof(bool) &amp;gt;= sizeof(Boolean) );&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return GetParameter&amp;lt;Boolean&amp;gt;( inName, sizeof( Boolean ), (Boolean*) outValue );&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;}&lt;/code&gt;&lt;/p&gt;
    &lt;p&gt;Adding the &lt;code&gt;CompileAssert&lt;/code&gt; not only makes the assumption explicit, it will generate a compiler error should we ever move this code to a system where the assumption is no longer valid. But that doesn&amp;rsquo;t really resolve the underlying problem.&lt;/p&gt;
    &lt;p&gt;Another attempt to resolve the problem might to replace the C-style cast with a C++ explicit &lt;code&gt;static_cast&lt;/code&gt;:&lt;/p&gt;
    &lt;p&gt;&lt;code&gt;//-----------------------------------------------------------------------------------&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;//&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetParameter&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;//-----------------------------------------------------------------------------------&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;//&lt;/code&gt;&lt;br&gt;&lt;code&gt;OSStatus&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;TCarbonEvent::GetParameter(&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;EventParamName&amp;nbsp;&amp;nbsp;inName,&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bool*&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; outValue )&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;{&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return GetParameter&amp;lt;Boolean&amp;gt;( inName,&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sizeof( Boolean ),&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static_cast&amp;lt;Boolean*&amp;gt; (outValue) );&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;}&lt;/code&gt;&lt;/p&gt;
    &lt;p&gt;This actually works provided that our particular compiler defines &lt;code&gt;bool&lt;/code&gt; in a manner that&amp;rsquo;s type equivalent to &lt;code&gt;Boolean&lt;/code&gt;. It has the added benefit that it will generate a compiler error should the underlying type-equivalence ever change. Unfortunately, if we&amp;rsquo;re already working with a compiler where &lt;code&gt;Boolean&lt;/code&gt; and &lt;code&gt;bool&lt;/code&gt; are not type equivalent, then our code no longer compiles. Metrowerks, for example, generates a compiler error with the message, &lt;code&gt;illegal explicit type cast from bool* to Boolean*&lt;/code&gt;.&lt;/p&gt;
    &lt;p&gt;For my money, the best solution is the pedantically correct solution:&lt;/p&gt;
    &lt;p&gt;&lt;code&gt;//-----------------------------------------------------------------------------------&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;//&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetParameter&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;//-----------------------------------------------------------------------------------&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;//&lt;/code&gt;&lt;br&gt;&lt;code&gt;OSStatus&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;TCarbonEvent::GetParameter(&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;EventParamName&amp;nbsp;&amp;nbsp;inName,&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bool*&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;outValue )&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;{&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;OSStatus result;&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Boolean value;&lt;/code&gt;&lt;br&gt;
    &lt;br&gt;
    &lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result = GetParameter&amp;lt;Boolean&amp;gt;( inName, sizeof( Boolean ), &amp;amp;value );&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (noErr == result)&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; *outValue = value != 0;&lt;/code&gt;&lt;br&gt;
    &lt;br&gt;
    &lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return result;&lt;/code&gt;&lt;br&gt;
    &lt;code&gt;}&lt;/code&gt;&lt;/p&gt;
    &lt;p&gt;Note that this solution doesn&amp;rsquo;t simply assign &lt;code&gt;value&lt;/code&gt; to the location in memory pointed to by &lt;code&gt;outValue&lt;/code&gt;. Rather it assigns the result of the Boolean expression &lt;code&gt;value != 0&lt;/code&gt; to &lt;code&gt;value&lt;/code&gt;.&lt;/p&gt;
    &lt;p&gt;When you work on a large software project with a number of other programmers, being so pedantically correct as to use real Boolean expressions for Boolean results will often mean the difference between code that works and plays well with others and code that introduces subtle bugs that can take you hours to track down, or worse, months before users actually discover that the bugs exist.&lt;/p&gt;
    &lt;p&gt;&amp;nbsp;&lt;/p&gt;
    &lt;p&gt;Rick&lt;/p&gt;
	&lt;p&gt;Currently playing in iTunes: &lt;i&gt;Rhyme &amp; Reason&lt;/i&gt; by Dave Matthews Band&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=406986" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/rick_schaut/archive/tags/Programming/default.aspx">Programming</category></item><item><title>MPW C Error Messages</title><link>http://blogs.msdn.com/rick_schaut/archive/2005/04/01/404529.aspx</link><pubDate>Fri, 01 Apr 2005 13:54:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:404529</guid><dc:creator>Rick Schaut</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/rick_schaut/comments/404529.aspx</comments><wfw:commentRss>http://blogs.msdn.com/rick_schaut/commentrss.aspx?PostID=404529</wfw:commentRss><description>&lt;p&gt;Those of us who've been programming the Mac for a few years have some fond memories of the old Macintosh Programmer's Workbench (MPW). It was very much like the Terminal Window on OS X, but had a few quirks of its own.&lt;/p&gt; &lt;p&gt;Among those quirks were the error messages that the C compiler would give you for certain errors. Messages like, "a typedef name was a complete surprise to me at this point in your program," and "String literal too long (I let you have 512 characters, that's 3 more than ANSI said I should)" almost made you want to write broken code just to see what the compiler had to say.&lt;/p&gt; &lt;p&gt;The most complete list of the error messages I could find is &lt;a href="http://www.effect.net.au/lukastan/humour/Computing-Software/Error-Messages-Mac.txt"&gt;here&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Well, rumor has it that there's a skunk works at Apple who are busy porting some of these error messages into XCode 2.0. And they say that Apple have lost their sense of humor...&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;Rick&lt;/p&gt; &lt;p&gt;Currently playing in iTunes: &lt;i&gt;Won't Get Fooled Again&lt;/i&gt; by The Who&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=404529" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/rick_schaut/archive/tags/History/default.aspx">History</category><category domain="http://blogs.msdn.com/rick_schaut/archive/tags/Programming/default.aspx">Programming</category></item><item><title>Hungarian Notation (Again)</title><link>http://blogs.msdn.com/rick_schaut/archive/2005/03/11/394045.aspx</link><pubDate>Fri, 11 Mar 2005 08:21:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:394045</guid><dc:creator>Rick Schaut</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/rick_schaut/comments/394045.aspx</comments><wfw:commentRss>http://blogs.msdn.com/rick_schaut/commentrss.aspx?PostID=394045</wfw:commentRss><description>&lt;p&gt;Cyrus is &lt;A href="http://blogs.msdn.com/cyrusn/archive/2005/03/07/389125.aspx"&gt;having difficulty&lt;/a&gt; parsing out the example given in &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnvs600/html/HungaNotat.asp"&gt;Simonyi's original article&lt;/a&gt; on the subject. I've blogged about this &lt;A href="http://blogs.msdn.com/rick_schaut/archive/2004/02/14/73108.aspx"&gt;before&lt;/a&gt;, but it's worth reiterating the main point of my earlier post.&lt;/p&gt; &lt;p&gt;It's somewhat unfortunate, because the example that Simonyi chose happens to be a rather bad example of Hungarian notation, though, arguably, it serves well to illustrate Simonyi's point about "dimensional anaylsis."&lt;/p&gt; &lt;p&gt;There's a really simple rule we can use to figure out whether or not we're using Hungarian notation correctly. If the name of the variable denotes nothing more than the language type of the variable, then we're using it &lt;em&gt;incorrectly&lt;/em&gt;. If the name of the variable reflects how it's being used in the program, then we're using Hungarian notation &lt;em&gt;correctly&lt;/em&gt;. In this sense, we can think of Hungarian notation as acronyms applied to variable names.&lt;/p&gt; &lt;p&gt;As an exercise, you might want to take Simonyi's example, and correct the usage. In particular, see if you can't think of a better prefix for the computed hash value. perhaps "hsz", or maybe simply "sh"?&lt;/p&gt; &lt;p&gt;By the way, there's a potential bug in Somonyi's example that's implied by the use of Hungarian notation. There is an extern integer declared as "bsyMac" in the code. This is a current maximum value within a collection. PsySz computes a new bsy, but doesn't update bsyMac. It should, either directly or indirectly.&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p&gt;Rick&lt;/p&gt; &lt;p&gt;Currently playing in iTunes: &lt;i&gt;Book Of Liars (Live)&lt;/i&gt; by Steely Dan &lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=394045" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/rick_schaut/archive/tags/Programming/default.aspx">Programming</category></item><item><title>AppleScript and VBA: the Story of Sid and Nancy</title><link>http://blogs.msdn.com/rick_schaut/archive/2004/08/05/208933.aspx</link><pubDate>Thu, 05 Aug 2004 14:30:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:208933</guid><dc:creator>Rick Schaut</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/rick_schaut/comments/208933.aspx</comments><wfw:commentRss>http://blogs.msdn.com/rick_schaut/commentrss.aspx?PostID=208933</wfw:commentRss><description>&lt;p&gt;In the few spare moments I&amp;rsquo;ve had over the past several weeks, I&amp;rsquo;ve followed
some discussions of Word and AppleScript both in the comments to my earlier
post and in the Microsoft newsgroups. A particularly good discussion, with
input from both Matt Neuburg and Paul Berkowitz, can be found &lt;a
href="http://groups.google.com/groups?hl=en&amp;amp;lr=&amp;amp;ie=UTF-8&amp;amp;th=20c988c80acc2b13&amp;amp;seekm=null-A0B28D.22454713072004%40news-west.sjc.giganews.com#link1"&gt;here&lt;/a&gt;.&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;

&lt;p&gt;Both Matt and Paul have pointed out that there is a very strong
correspondence between AppleScript and Word&amp;rsquo;s VBA (Visual Basic for
Applications) implementation. The same is true for both PowerPoint and Excel,
though not for Entourage. There is no VBA implementation in Entourage.&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;

&lt;p&gt;I want to talk about why AppleScript so closely resembles VBA in Word, Excel
and PowerPoint, but I first want to take a step back and talk about objects and
object models.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;These are terms you&amp;rsquo;ll
find quite often in any discussion of scripting regardless of the application
or the scripting environment.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;It
has a lot to do with how programmers think about the data they manipulate and
how they manipulate it.&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;

&lt;p&gt;An &amp;ldquo;object&amp;rdquo; is any entity that can respond to some form of input or command,
and often has some form of data associated with it.&lt;span style="mso-spacerun:
yes"&gt;&amp;nbsp; &lt;/span&gt;Word, as an application, is an object.&lt;span
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;The documents that you have open in
Word are objects.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;The windows that
display those documents are objects.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;
&lt;/span&gt;The sections within those documents are objects.&lt;span
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;The paragraphs within the sections are
objects.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;In formal terms, an
object is both the data it contains and the operations that can be performed on
the data it contains.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;We use the
word &amp;ldquo;properties&amp;rdquo; to talk about the data, and the word &amp;ldquo;methods&amp;rdquo; (or &amp;ldquo;commands&amp;rdquo;
in AppleScript parlance) to talk about the operations that can be performed on
that data.&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;

&lt;p&gt;An &amp;ldquo;object model&amp;rdquo; is a conceptual definition, or description, of how the
objects in an application are related to each other.&lt;span style="mso-spacerun:
yes"&gt;&amp;nbsp; &lt;/span&gt;Quite often this takes shape in the form of a &amp;ldquo;containment
hierarchy&amp;rdquo;.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;The &amp;ldquo;containment
hierarchy&amp;rdquo; is really just a fancy way of saying that some objects are
properties of other objects.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;For
example, in Word, a paragraph is a property of the document object.&lt;span
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;This relationship can include the notion
of collections (or &amp;ldquo;plural forms&amp;rdquo; in AppleScript parlance).&lt;span
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;Really, a collection is nothing more
than a group of similar objects within the same container.&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;

&lt;p&gt;Any given object model is very application centric.&lt;span
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;Word&amp;rsquo;s object model, for example, has
some significant differences from, say, BBEdit&amp;rsquo;s object model, and that&amp;rsquo;s not
just because Word does some things that BBEdit doesn&amp;rsquo;t.&lt;span
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;The way one describes the &amp;ldquo;selection&amp;rdquo;
object is highly dependant upon how the concept of a &amp;ldquo;selection&amp;rdquo; is implemented
in that application.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;The &amp;ldquo;selection&amp;rdquo;
object for a drawing program, for example, is going to be very different from
the &amp;ldquo;selection&amp;rdquo; object in a text editor.&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;

&lt;p&gt;Commands and how they relate to objects are also extremely application
centric.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;For example, when you
tell an application to &amp;ldquo;select foo of bar,&amp;rdquo; what does that really mean?&lt;span
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;Are you telling &amp;ldquo;foo of bar&amp;rdquo; to select
itself, are you telling the selection object to incorporate &amp;ldquo;foo of bar,&amp;rdquo; or
are you telling the application to change its selection to foo of bar?&lt;span
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;The answer to that question will depend
largely on the application you&amp;rsquo;re working with (though, in Word, it generally
means that you&amp;rsquo;re asking &amp;ldquo;foo of bar&amp;rdquo; to become the selection).&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;

&lt;p&gt;The important point in all of this is that, at the conceptual level, the
object model one defines for any given application depends on the application,
and not the scripting environment or scripting language you use to expose that
object model.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;Had Word never had a
VBA implementation of its object model, Word&amp;rsquo;s AppleScript implementation of
that object model would not have differed substantially from its current
implementation.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;Any differences
would be more attributable to the way particular individuals approached the
design of the object model than they would be attributable to differences
between VBA and AppleScript.&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;

&lt;p&gt;This is the primary reason why there is such a strong correspondence between
the VBA implementation and the AppleScript implementation of the object models
in Word, Excel and PowerPoint.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;One
could, if one wanted to, implement VBA as a pass-through to an AppleScript
implementation of these object models, though there is a fundamental difference
between VBA and AppleScript that would tend to favor doing things the other way
around.&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;

&lt;p&gt;To understand this fundamental difference, we have to understand something
known as &amp;ldquo;application intercommunication,&amp;rdquo; or &amp;ldquo;interprocess communication&amp;rdquo; (the
word &amp;ldquo;process&amp;rdquo; is really just a synonym for &amp;ldquo;application program&amp;rdquo;).&lt;span
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;Within modern operating systems,
applications have fences built around them.&lt;span style="mso-spacerun:
yes"&gt;&amp;nbsp; &lt;/span&gt;The idea is to keep bugs in one application from affecting
the behavior of other applications running on the system.&lt;span
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;Within this design, if applications are
going to communicate with each other, we need to give them a way to pass
information back and forth over the fences that have been built around them.&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;

&lt;p&gt;With AppleScript, interprocess communication is done via AppleEvents.&lt;span
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;Every command that you send to Word via
AppleScript is packaged up into an AppleEvent.&lt;span style="mso-spacerun:
yes"&gt;&amp;nbsp; &lt;/span&gt;When Word&amp;rsquo;s done processing that AppleEvent, it packages up
a reply, puts the reply in the AppleEvent, and sends it back &amp;ldquo;over the fence&amp;rdquo;
as it were.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;With VBA, interprocess
communication is done using the Component Object Model (or COM).&lt;span
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;COM provides programming interfaces
that are amenable to being called directly within the programming languages we
use to write the applications themselves.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;
&lt;/span&gt;COM is often referred to as a &amp;ldquo;binary interface,&amp;rdquo; because it lends
itself to direct programmatic manipulation in this way.&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;

&lt;p&gt;In essence, COM was designed so that objects in the system would look an
awful lot like they way objects are implemented in the C++ programming
language.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;In fact, you can take a
file written in the COM Object Description Language (ODL) and, using a
command-line tool, generate header files that can be included directly into C++
code.&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;

&lt;p&gt;For interprocess communication, COM has a technical problem that I won&amp;rsquo;t
describe in detail, but involves the fact that applications have fences built
around them.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;Basically, one
program cannot directly call a binary interface that&amp;rsquo;s provided by another
program.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;That would be like
reaching through the fence instead of passing something over the fence.&lt;span
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;To solve this, COM uses something
called &amp;ldquo;marshalling&amp;rdquo;.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;None of this
has to be done for AppleScript, because AppleScript doesn&amp;rsquo;t provide the same
kind of binary interface.&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;

&lt;p&gt;So, COM is messy for &lt;em&gt;inter&lt;/em&gt;process communication, but it&amp;rsquo;s really
nice for &lt;em&gt;intra&lt;/em&gt;process communication.&lt;span style="mso-spacerun:
yes"&gt;&amp;nbsp; &lt;/span&gt;AppleScript isn&amp;rsquo;t quite so messy when it comes to &lt;em&gt;inter&lt;/em&gt;process
communication, but it&amp;rsquo;s a royal PITA when it comes to &lt;em&gt;intra&lt;/em&gt;process
communication.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;What do I mean by &lt;em&gt;intra&lt;/em&gt;process
communication?&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;Well &lt;em&gt;intra&lt;/em&gt;process
communication is how various software components in an application, and in any
shared libraries used by that application, communicate with each other.&lt;span
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;In this case, the kind of binary
interface that COM provides is perfect.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;
&lt;/span&gt;To the programmer, the COM objects look like any other component in the
program (which is where the name &amp;ldquo;COM&amp;rdquo; comes from).&lt;/p&gt;

&lt;p&gt;This is, in fact, how all of the external wizards that we ship are
implemented.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;They&amp;rsquo;re written in
C++ and they talk to Word, or Excel or PowerPoint, via the binary interfaces
each of the applications expose through the VBA implantations of their
respective object models.&lt;/p&gt;

&lt;p&gt;For those of you who are familiar with COM and the standard programming
interfaces that COM defines, I should point out that all of these interfaces
are &amp;ldquo;dual dispatch&amp;rdquo; interfaces.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;
&lt;/span&gt;While every object does implement the standard IDispatch interface,
every method and every property of every object is also available through
direct programmatic manipulation through individual interfaces that descend
from IDispatch.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;The point is that
neither the Wizards we ship nor the AppleScript implementation goes through
IDispatch::Invoke.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;Rather, both
call the appropriate method or property implementation directly on the
appropriate object itself.&lt;/p&gt;

&lt;p&gt;If you don&amp;rsquo;t understand anything in the above paragraph, don&amp;rsquo;t worry.&lt;span
style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;The important point to understand is
that, in light of the previous point about the design of an object model for
any given application, it makes perfect sense to use an existing VBA
implementation of an object model to expose that same object model via
AppleScript.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;In fact, not only
does it make perfect sense to do this, it&amp;rsquo;s the most efficient way you can
possibly do the job.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;The VBA
implementation already packages up the object model in a manner that lends
itself to direct programmatic manipulation.&lt;/p&gt;

&lt;p&gt;It makes so much sense to do things this way that you can even get lazy
about it.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;You can design a
language that describes your object model both in VBA and AppleScript terms,
and then you can write a tool that parses a description file and generates the
code for you.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;In only a &amp;ldquo;few&amp;rdquo;
(quoted because &amp;ldquo;few&amp;rdquo; is relative&amp;#8212;there are 215 distinct objects in Word&amp;rsquo;s
object model, and I won&amp;rsquo;t even begin to count all the properties and methods on
those objects) instances do you have to get your hands dirty and write some
code yourself.&lt;/p&gt;

&lt;p&gt;As an insight into Jim Murphy&amp;rsquo;s sense of humor, the object description language
is called &amp;ldquo;Sid,&amp;rdquo; and the tool that compiles files written in that language is
called &amp;ldquo;Nancy.&amp;rdquo;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;One of these days,
I&amp;rsquo;m going to have to go rent that movie.&lt;/p&gt;

&lt;p&gt;&lt;![if !supportEmptyParas]&gt;&amp;nbsp;&lt;![endif]&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;

&lt;p&gt;Rick&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;
&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=208933" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/rick_schaut/archive/tags/Programming/default.aspx">Programming</category><category domain="http://blogs.msdn.com/rick_schaut/archive/tags/Microsoft+Word/default.aspx">Microsoft Word</category></item><item><title>Anatomy of a Software Bug</title><link>http://blogs.msdn.com/rick_schaut/archive/2004/05/19/135315.aspx</link><pubDate>Wed, 19 May 2004 20:50:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:135315</guid><dc:creator>Rick Schaut</dc:creator><slash:comments>90</slash:comments><comments>http://blogs.msdn.com/rick_schaut/comments/135315.aspx</comments><wfw:commentRss>http://blogs.msdn.com/rick_schaut/commentrss.aspx?PostID=135315</wfw:commentRss><description>&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Anatomy of a Software Bug&lt;/title&gt;
&lt;/head&gt;

&lt;body bgcolor=white lang=EN-US style='tab-interval:.5in'&gt;

&lt;div class=Section1&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;Chris Mason is the person who hired me to work at Microsoft. By the time he
hired me, he&amp;rsquo;d already spent a great deal of time looking into the issue of
general software quality, and had written a memo (known as the &amp;ldquo;Zero Defects&amp;rdquo;
memo) that underlies much of our software practices today. The ideas have been
refined since then, but they haven&amp;rsquo;t changed much in terms of the basic
concepts.&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;One of my favorite Chris Mason quotes comes from that memo, &amp;ldquo;Since human
beings themselves are not fully debugged yet, there will be bugs in your code
no matter what you do.&amp;rdquo; We work to minimize the bugs in the software we ship,
but they&amp;rsquo;ll always be there.&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;The problem stems from the overall complexity of the software. In this
context, &amp;ldquo;complexity&amp;rdquo; doesn&amp;rsquo;t refer to the code itself. Rather, we&amp;rsquo;re talking
about the shear volume of things the user can do. In Word, for example, we
have:&lt;/p&gt;

&lt;ul&gt;

&lt;li style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;More than 850 command functions (e.g. Bold and Italic are the
same command function)&lt;/li&gt;

&lt;li style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;More than 1600 distinct commands (e.g. Bold and Italic are
distinct commands)&lt;/li&gt;

&lt;li style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;At any given time roughly 50% of these commands are enabled
(conservative estimate)&lt;/li&gt;

&lt;li style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;With just 3 steps, the possible combinations of code execution
paths exceeds 500 million&lt;/li&gt;

&lt;/ul&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;Now, there&amp;rsquo;s a philosophical issue about the desirability of increasingly
complex software, but I&amp;rsquo;m not going to discuss it here. For all practical
purposes, I don&amp;rsquo;t think there&amp;rsquo;s much benefit to getting into a discussion about
it. It may be an interesting question on some level, but it&amp;rsquo;s one we&amp;rsquo;ll never
fully resolve. And I&amp;rsquo;m just not all that interested in getting bogged down in
an endless debate without the possibility of resolution.&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;I mention the issue of complexity because it leads to subtle interactions
that can be difficult to track down. To illustrate the point even further, I
thought I&amp;rsquo;d discuss the anatomy of one of the more famous bugs we&amp;rsquo;ve had in
Word: the &amp;ldquo;Disk is full&amp;rdquo; on save error. Before I do, however, I should point
out that Pierre Igot, after some prodding on my part, did provide us with a
sample document that helped us to track down one of the more subtle
interactions involved in this particular problem. For that, Pierre, I thank you
and so do Word users everywhere.&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;The story of this problem begins with a basic design decision made when
Richard Brodie was Word&amp;rsquo;s primary software architect. Brodie came to Microsoft
along with Charles Simonyi after working at the Xerox PARC where he&amp;rsquo;d worked on
Bravo&amp;#8212;their version of the GUI word processor. A number of the ideas used
in Word came from that early effort. Brodie joined Microsoft in 1981, began
work on Word in the summer of 1982, and finished version 1.0 in October of 1983.
You can read about much of the story in &lt;i&gt;Microsoft First Generation&lt;/i&gt;&lt;span
style='font-style:normal'&gt; by Cheryl Tsang.&lt;/span&gt;&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;Brodie figured out that a document is really just a collection of pieces of
text, and that it didn&amp;rsquo;t really matter where each piece of text is physically
located within the document&amp;rsquo;s file. For that matter, you could have one piece
of text that came from one file and another piece of text that came from
another file. We refer to this collection of pieces of text as the &amp;ldquo;piece
table.&amp;rdquo;  This design has a number of benefits. For example, if you copy text
from one document to another, you don&amp;rsquo;t have to actually copy the text from one
file to another&amp;#8212;at least not right away. All you really need to do is
copy the appropriate entries in the piece table in the source document to the
piece table in the destination document. Of course, you do need to copy the
physical text and formatting from one file to the other when you save the
destination document, but delaying that physical copy until save time meant
that the actual copy/paste could be done very quickly.&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;This design also made implementing undo rather simple. In fact, according to
Brodie, implementing undo was the primary reason to use this design. With this
design, all you have to do is create an internal undo document. When the user
deletes some text from the current document, for example, you copy the deleted
entries from the piece table to the undo document and save some information
about where those piece-table entries had been located in the original document.
To undo the delete, you just copy the piece-table entries from the undo
document back to the original document.&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;This design does have one problem: where do you put the text that the user
types into the document if it doesn&amp;rsquo;t go into the file that&amp;rsquo;s behind the
document?  To solve that, Brodie added something called a &amp;ldquo;scratch&amp;rdquo; file, and
the scratch file remains a core part of Word&amp;rsquo;s design to this day. On the Mac,
Word creates this file in your TemporaryItems folder. On Mac OS X, this folder
is located at /private/tmp/&amp;lt;UID&amp;gt;/TemporaryItems, where &amp;ldquo;UID&amp;rdquo; is your user
ID number (for most people, that&amp;rsquo;s 501, but it can be a different number
altogether depending on how your user account was created). If start up Word,
open the terminal window and get a listing of your TemporaryItems folder, you&amp;rsquo;ll
see a file named something like &amp;ldquo;Word Work File S_.&amp;rdquo; There may be a number
after the &amp;ldquo;_&amp;rdquo; character. That&amp;rsquo;s Word&amp;rsquo;s scratch file (the &amp;ldquo;S&amp;rdquo; standing for
scratch). You might also see one or more files named &amp;ldquo;Word Work File D_&amp;rdquo; with
some number after the &amp;ldquo;_&amp;rdquo; character. This is a back-up copy of a document file
(the &amp;ldquo;D&amp;rdquo; standing for &amp;ldquo;Document&amp;rdquo;).&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;At this point, we need to fast-forward the story by a decade to the next major
feature that brought this problem to the fore: multiple undo. For ten years,
Word had undo, but it was just a single-level undo. For Word 6, we added the
ability to go back and undo every change you&amp;rsquo;d made to the document since you
first started editing it. And, with Word&amp;rsquo;s document/file architecture, this
wasn&amp;rsquo;t all that difficult to do: just make the undo document contain multiple
records with one record for each change to the main document. It&amp;rsquo;s a very cool
feature, and most of us couldn&amp;rsquo;t think of how we&amp;rsquo;d survive without it. But it
leads to a problem.&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;It&amp;rsquo;s not uncommon for users to make a few edits to a document, save the
document, make a few more edits, save the document again, make a few more
changes, and continue this process of edit/save for hours on end. Each time you
delete text, however, the actual text itself exists in the last-saved file for
the document you&amp;rsquo;re editing, and, with multiple levels of undo, the undo
records for text deletions still point back to the last-saved version of the
document&amp;rsquo;s file before you deleted the text. The next time you save, Word can&amp;rsquo;t
close the last-saved version of the file, because the undo document still
contains a reference to it. So, if you keep editing and saving, you&amp;rsquo;ll
eventually hit an open file limit.  At least this was true of Word 6.  It&amp;rsquo;s
changed quite a bit since then.&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;Arguably, this is something we should have figured out before we shipped Word
6, but, as Chris Mason pointed out, we humans haven&amp;rsquo;t been fully debugged yet. 
Moreover, it&amp;rsquo;s easy to say that one should have thought of a particular
interaction in a complex piece of software, but that&amp;rsquo;s way easier said than
done.  When you&amp;rsquo;re implementing any given feature, you&amp;rsquo;re totally focused on
the basic problems involved in the feature itself.  To put this into
perspective, the person who implemented multiple undo in Word is one of the
best developers who has ever worked on Word, and has, since, been recognized as
a Microsoft Distinguished Engineer.&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;The reality is, that we hadn&amp;rsquo;t realized we&amp;rsquo;d created this situation when we
added multiple levels of undo. Moreover, this problem has several different
variations on the basic theme. At this point, the story involves our efforts to
understand the nature and scope of the problem, and to come up with the &amp;ldquo;best&amp;rdquo;
way to fix it. Because of the variations, however, the problem has been like an
onion. We&amp;rsquo;d peel away one layer of the onion, only to find some other variation
that we hadn&amp;rsquo;t, for various reasons, figured out before.&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;As we weave our way through the rest of the story, there are some important
points to keep in mind. The first is that I can&amp;rsquo;t fix what I can&amp;rsquo;t see, and, where
software bugs are concerned, &amp;ldquo;seeing&amp;rdquo; means being able to watch the program
execute, via some debugging tool, at the key point in the execution of the code
where the problem occurs. In order to do this, I have to have a precise set of
steps that consistently reproduces the problem. This not all that different from
the problem a mechanic faces when trying to figure out the cause of that
mysterious engine noise that only occurs after you&amp;rsquo;ve been driving the car
around town for a few hours.&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;The second is that this particular problem is a developer&amp;rsquo;s worst nightmare.
The fundamental cause is a basic design decision that you made more than a
decade ago, and the only way to really fix it for certain is to rewrite the
entire application from the ground up. Since that&amp;rsquo;s simply not an option for a
product that you&amp;rsquo;ve shipped several times, you&amp;rsquo;re left with trying to make the
problem difficult for most users to run into while trying to also minimize the
negative effects if the user should ever run into the problem. This approach
can, unfortunately, lead you to believe that you&amp;rsquo;ve come up with an &amp;ldquo;optimal&amp;rdquo;
fix only to discover later that there&amp;rsquo;s another facet you haven&amp;rsquo;t taken into
consideration (because you didn&amp;rsquo;t even know it existed until you peeled away
the previous layer of the onion).&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;The third point to keep in mind is that we in Mac BU have relatively limited
resources. When there&amp;rsquo;s a problem that&amp;rsquo;s fundamental to Word itself, we tend to
let our Win Word siblings focus on that problem. Our efforts tend to have little
chance of adding to their efforts, and this frees us up to focus on problems
specific to Mac users. In general, this is the most efficient way to handle
problems that our users are having, but there can be instances where there&amp;rsquo;s a
Mac-specific dimension to a problem. As we&amp;rsquo;ll see soon enough, this particular
problem had a Mac-specific dimension that complicated our efforts to fix it,
and it took us a while to find that Mac-specific dimension.&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;Lastly, the fact that Mac Word&amp;rsquo;s code base has been forked from Win Word&amp;rsquo;s
means that the Win Word people can make a change in the code for one reason,
and that change can have other side-effects that we won&amp;rsquo;t see in the Mac
version until we run into some very specific circumstances that show us the
different behaviors caused by this change. In this particular case, Win Word
added two lines of code in a routine that would seemingly be completely
unrelated to this problem, but also made this problem much more difficult for
users to run into in Win Word than it was in Mac Word. This one is the last
piece (maybe I should say &lt;i&gt;latest&lt;/i&gt;&lt;span style='font-style:normal'&gt; piece)
in the puzzle that we discovered only a few months ago.&lt;/span&gt;&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;Whew!  That&amp;rsquo;s a lot to keep in the back of our heads, but, nonetheless, let&amp;rsquo;s
rewind back about ten years. Word 6.0 has just shipped on Windows, and we&amp;rsquo;re
pretty happy with people&amp;rsquo;s reactions to the product. It doesn&amp;rsquo;t take long,
though, for us to figure out that there&amp;rsquo;s a fly in the ointment. Reports start
trickling in about people editing their documents &amp;ldquo;for a while&amp;rdquo; at which point
they try to save their document and they get a &amp;ldquo;Disk is full&amp;rdquo; error. We&amp;rsquo;d ask
people what they were doing, and the response was always some form of vague
notion that they&amp;rsquo;d just been editing their document &amp;ldquo;for a while.&amp;rdquo;  The precise
measurement of &amp;ldquo;for a while&amp;rdquo; varied from user to user. For some folks, it was a
little over an hour. For others, it was several hours. Reproducing the problem
appeared to be highly dependant upon the user&amp;rsquo;s work habits.&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;After several months of trying to figure out the problem, someone in testing
wrote a macro that inserted a large amount of text into the document and then,
in a loop, replace successive words within the document saving it after each
replace. Run this macro for a while, and you get a &amp;ldquo;Disk is full&amp;rdquo; error on one
of the saves, at which point you can no longer save your document. Cool!  We
now have steps that reproduce the problem.&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;So, this document got handed off to a developer, who then fired up Word
under the debugger, opened the document and ran the macro. The problem &amp;ldquo;reproduced,&amp;rdquo;
but, for reasons that weren&amp;rsquo;t apparent at the time, the error that the
developer ran into was subtly different from the error that the tester ran into.
The developer thought about the problem he was seeing, and came up with one of
those &amp;ldquo;optimal&amp;rdquo; fixes I mentioned above. It was the &amp;ldquo;right&amp;rdquo; fix in terms of the
problem the developer saw, but it wasn&amp;rsquo;t the &amp;ldquo;right&amp;rdquo; fix for the problem that
the tester saw.&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;What was this subtle difference between what the developer saw and what the
tester saw?  As I mentioned above, the basic theme of the problem is to hit &lt;i&gt;an&lt;/i&gt;&lt;span
style='font-style:normal'&gt; open file limit. In this case, there are two limits:
Word&amp;rsquo;s internal open file limit and the OS&amp;rsquo; open file limit. It turns out that
the debugger bumps the OS&amp;rsquo; open file limit from what it would normally be when
you run Word outside the debugger. When the tester ran the macro, Word hit the
OS&amp;rsquo; open file limit. When the developer ran the macro, with Word running under
the debugger, Word ran into its own, internal, file limit.&lt;/span&gt;&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;After a few iterations of the tester saying, &amp;ldquo;Sorry, but the bug&amp;rsquo;s not fixed
yet,&amp;rdquo; and the developer saying, &amp;ldquo;What are you talking about? I don&amp;rsquo;t see the
problem!&amp;rdquo; they both figured out that they were seeing different errors. Crap! 
The problem only reproduces when you&amp;rsquo;re &lt;i&gt;not&lt;/i&gt;&lt;span style='font-style:normal'&gt;
running under the debugger, which removes the one case where the developer can
actually see what&amp;rsquo;s going on. At this point, we have yet to figure out that the
problem involves hitting the OS&amp;rsquo; open file limit. At this point, though, the
developer isn&amp;rsquo;t completely in the dark, and comes up with a fix for the tester&amp;rsquo;s
problem.&lt;/span&gt;&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;As I pointed out, the problem involves the undo document having a reference
to the previously saved-version of the document&amp;rsquo;s file. The developer&amp;rsquo;s
original fix was to add some code, in the case where Word hit its internal open
file limit, that would basically remove everything from the undo document (what
we refer to as &amp;ldquo;nuking the undo stack&amp;rdquo;). Nuking the undo stack allows the save
to proceed, because Word can now close the open files that were referenced by
the undo document. However, since the tester was seeing a different error, the
developer&amp;rsquo;s fix didn&amp;rsquo;t handle that case.&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;Nonetheless, the developer took a different approach. Knowing that the undo
document was very likely to be involved, one could walk through the undo
document, and copy the text for any pieces that pointed to the previously-saved
version of the document&amp;rsquo;s file to the scratch file. He coded up the solution,
and handed a buddy-build off to the tester. The tester ran the macro, and the
problem was fixed. The first layer of the onion had been peeled away, but the
fix still wasn&amp;rsquo;t an &amp;ldquo;optimal&amp;rdquo; fix. As it stood, the chances that a user would
run into the problem had been greatly reduced, but we still hadn&amp;rsquo;t dealt with
the &amp;ldquo;minimize the damage if they do hit it&amp;rdquo; side of the issue. That&amp;rsquo;s because,
at this point, we had yet to understand that the problem outside the debugger
had to do with the OS&amp;rsquo; open file limit. Because this problem wouldn&amp;rsquo;t reproduce
under the debugger, the developer had no way of knowing exactly where the
failure was occurring. Without knowing that, the developer didn&amp;rsquo;t know where to
add the code that would &amp;ldquo;nuke the undo stack.&amp;rdquo;&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;To give you a sense of the time frame, this fix was ported from Win Word to
Mac Word during the Office 2001 development cycle, and was back-ported into
Word 98 for a service release that was done not too long after that. It&amp;rsquo;s also
at this point where the Win Word and Mac Word stories diverge. There are two
reasons for this. The first is that this was the point in time where Win Word
got that two-line code change that I mentioned above. The second is that the
open file limit under Mac OS is different than it is under Windows. I might be
mistaken on this point, but I think the open file limit under Mac OS X is
different from the limit under Mac OS 9 as well.&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;At this point, we still didn&amp;rsquo;t know that the basic problem involved hitting
the OS&amp;rsquo; open file limit. After a while, though, we did know that Mac Word users
were seeing this problem way more often than Win Word users. In fact, the
difference was enough for Mac Word testers to start investigating the problem
directly. One of the things we did know is that the problem involved file
references in the undo document. So, we came up with a variation of the
original fix.&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;In order to understand this, we have to understand a basic principle of
fixes. You make the simplest code change required to fix the problem. This
reduces the chances that the fix will cause some other problem that is,
potentially, worse than the one you&amp;rsquo;re trying to fix. When you&amp;rsquo;re mucking about
with the locations where data is stored in files, the potential for
catastrophic problems resulting from your fix is high. In that sense, the
original fix for this problem was limited to copying what might be known as &amp;ldquo;simple&amp;rdquo;
pieces. A &amp;ldquo;simple&amp;rdquo; piece has only text. A &amp;ldquo;complex&amp;rdquo; piece might have a graphic,
or it might involve a field in the document, both of which are likely to have
data in the file in addition to the text itself.&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;With this in mind, for Mac Word X, we modified the notion of what would be a
&amp;ldquo;simple&amp;rdquo; piece of text for the sake of deciding whether or not to copy a piece
from the previously-saved document&amp;rsquo;s file over to the scratch file. To view
this in a slightly different way, we made the code that copies undo document
referents more aggressive. This resolved another test case that the Mac Word
testers had developed, again using a slightly different macro that would
eventually cause the &amp;ldquo;Disk is full&amp;rdquo; error to occur. This fix didn&amp;rsquo;t actually
make it into the shipping release of Mac Office X, but it was included in a
subsequent SR (I don&amp;rsquo;t recall specifically which one).&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;At this point, we &lt;i&gt;still&lt;/i&gt;&lt;span style='font-style:normal'&gt; don&amp;rsquo;t know that
the problem involves the OS&amp;rsquo; open file limit. That discovery didn&amp;rsquo;t happen
until this past summer when, through the very persistent efforts of Mac Word&amp;rsquo;s
current lead tester, we were able to use some tools on Mac OS X to figure out
exactly what was happening. While we were able to verify this, we still didn&amp;rsquo;t
know the exact location where Word was failing to open a file due to having hit
the OS&amp;rsquo; open file limit. Again, we still can&amp;rsquo;t get this to reproduce under the
debugger, and there are a couple of places in the save process where it can
fail because the OS won&amp;rsquo;t let Word open the file. So, rather than scatter fixes
all over the place, we went with the sure fix: lower Word&amp;rsquo;s internal open file
limit so we hit it before we hit the OS&amp;rsquo; open file limit. This allows the code
that nukes the undo stack to kick in, and then save the succeeds.&lt;/span&gt;&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;This brings us to late February/early March of this year, and the discussion
I&amp;rsquo;d had with Pierre. While we still can&amp;rsquo;t reproduce the actual file open
failure under the debugger, we now have enough information about what causes
the problem to be able to predict when the failure will eventually occur. From
that, we knew enough about the bug for me to believe that Pierre shouldn&amp;rsquo;t
still be hitting that &amp;ldquo;Disk is full&amp;rdquo; save error in the version of Word he was
using. Yet, he was still running into the problem.&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;That was the bad news: there was something about this problem that we still
didn&amp;rsquo;t fully understand. However, armed with a sample document and the ability
to predict when the error will occur, I could do something we&amp;rsquo;d never been able
to do before: set up Word under the debugger, perform some steps in Word to see
if those steps caused the predictive condition to occur, and set breakpoints
that would tell me exactly why we weren&amp;rsquo;t able to copy pieces from the undo
document over to the scratch file.&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;This is where I discovered those two lines of code that had been added to
Win Word so long ago, yet hadn&amp;rsquo;t been added to Mac Word. When Word lays out a
page in page layout view and a header or footer is visible, it updates any
fields in the header or footer. If you have, say, a page field in the visible
header/footer, Word will update that field. This is particularly necessary when
you have the footer of one page and the header of the following page both
visible in the document window. Word has to layout two pages in the same
update, so it updates fields for the first page footer, lays out that page,
then updates the fields for the next page header and lays out that page.&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;Now, why would this result in a field being copied over to the undo
document?  Well, Word has something called &amp;ldquo;auto undo tracking.&amp;rdquo;  Basically,
when you&amp;rsquo;re typing, Word automatically tracks the changes you&amp;rsquo;re making until
you do something that causes Word to close out the &amp;ldquo;typing&amp;rdquo; undo record. You
can see this when you click on the &amp;ldquo;Undo&amp;rdquo; dropdown on the standard toolbar. You&amp;rsquo;ll
see &amp;ldquo;Typing &amp;lt;text you typed&amp;gt;&amp;rdquo; at various locations in the dropdown
interspersed with other actions you&amp;rsquo;ve taken.&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;The two lines of code that were added to Win Word paused automatic undo
tracking while updating these fields in the header or footer during page
layout, then un-paused automatic undo tracking once the field update was
finished. Ugh!  How, on earth, were we to ever figure out that these two lines
of code were the primary reason Win Word users weren&amp;rsquo;t seeing this problem
nearly as often as Mac Word users?  In any event, if you&amp;rsquo;ve stayed with me long
enough, here&amp;rsquo;s a tip you can use until we release an SR of Word X (or earlier)
with this fix. If you have a document that has headers and footers with page
fields in them, do your editing in Normal view, and you&amp;rsquo;ll likely never hit the
&amp;ldquo;Disk is full&amp;rdquo; save error.&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;Right about now, you&amp;rsquo;re probably asking, &amp;ldquo;Why did it take so long to figure
out what was up with this?&amp;rdquo;  Well, you might as well ask why police departments
continue to have a large number of unsolved crimes on the books. The issue is the
same: the investigation stalls for the lack of any further leads to follow. For
the same reason that the police can&amp;rsquo;t just go out and start arresting anyone
who might be a suspect, we can&amp;rsquo;t go scattering potential fixes throughout the
code. Until we figure out what the precise nature of the problem is, we need
leads that we can follow. The mere fact that you&amp;rsquo;re running into a particular
problem isn&amp;rsquo;t a lead that I can follow. Specific details about potential
suspects, however, are leads I can follow. When it comes to software problems, leads
I can follow consist of information that helps me to reproduce the problems
consistently.&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;And, always remember that I can&amp;rsquo;t fix what I can&amp;rsquo;t see. I have to be able to
reproduce the problem while being able to run some kind of diagnostic tool. The
key to fixing a bug is predictability. Without predictability, I can&amp;rsquo;t fix it,
because without predictability I have no way to understand how the complex
interactions in modern software cause the specific problem to occur.&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;&amp;nbsp;&lt;/p&gt;

&lt;p style='font-size:11pt;font-family:Times New Roman, Times, serif'&gt;Rick&lt;/p&gt;

&lt;/div&gt;

&lt;/body&gt;

&lt;/html&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=135315" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/rick_schaut/archive/tags/History/default.aspx">History</category><category domain="http://blogs.msdn.com/rick_schaut/archive/tags/Programming/default.aspx">Programming</category><category domain="http://blogs.msdn.com/rick_schaut/archive/tags/Microsoft+Word/default.aspx">Microsoft Word</category></item></channel></rss>