原文链接:https://devblogs.microsoft.com/oldnewthing/20040910-00/?p=37903
I didn’t debug it personally, but I know the people who did. During Windows XP development, a bug arrived on a computer game that crashed only after you got to one of the higher levels.
我并不亲自进行调试工作,不过我认识做这项工作的人。在 Windows XP 的开发过程中,曾经有款游戏的一个 bug,只有玩到进度比较深入的时候才会显现,并使游戏崩溃。
After many saved and restored games, the problem was finally identified.
存档读档很多次之后,问题终于定位出来了。
The program does its video work in an offscreen buffer and transfers it to the screen when it’s done. When it draws text with a shadow, it first draws the text in black, offset down one and right one pixel, then draws it again in the foreground color.
游戏的程序在一处屏幕外的缓冲区中处理图像,当处理完成后,再传输到屏幕上。绘制带阴影的文字时,程序会先以黑色将文字绘制一遍,将其向右、向下移动各1个像素,然后再用前景色将文字绘制出来。
So far so good.
到此为止还没什么问题。
Except that it didn’t check whether moving down and right one pixel was going to go beyond the end of the screen buffer.
只是开发商忘了检查向右、向下移动各1个像素的时候,有没有超出屏幕缓冲区的边界。
That’s why it took until one of the higher levels before the bug manifested itself. Not until then did you accomplish a mission whose name contained a lowercase letter with a descender! Shifting the descender down one pixel caused the bottom row of pixels in the character to extend past the video buffer and start corrupting memory.
这就是为什么只有打到高等级的时候 bug 才会显现,因为直到那时才会完成一个任务,而这个任务的名字里有一个带下延部(注1)的小写字母!将这个字母的下延部下移1个像素,会导致底部一行的像素超出视频缓冲区,进而损毁了内存数据。
Once the problem was identified, fixing it was comparatively easy. The application compatibility team has a bag of tricks, and one of them is called “HeapPadAllocation”. This particular compatibility fix adds padding to every heap allocation so that when a program overruns a heap buffer, all that gets corrupted is the padding. Enable that fix for the bad program (specifying the amount of padding necessary, in this case, one row’s worth of pixels), and run through the game again. No crash this time.
找到问题的根源后,修复起来就相对比较容易了。应用程序兼容性团队有一口袋的戏法,其中之一名叫『HeapPadAllocation』。这一兼容性修复补丁会为每个堆分配增加一块补丁,这样当程序发生了堆缓冲区溢出的问题时,弄坏的就只是这块补丁而已。为这个惹事的程序启用这个补丁(指定所需的补丁大小,此处即1行像素的尺寸),再运行游戏,就不会再崩溃了。
What made this interesting to me was that you had to play the game for hours before the bug finally surfaced.
这件事让我感到有趣的一点是,你得把这款游戏先玩上4个小时,然后bug才会崭露头角。
注1:在西文字体排印学中,降部(英语:Descender)指的是一个字体中,字母向下延伸超过基线的笔画部分,也称为下延部。如图所示,字母y第二笔的“尾巴”部分就是降部。另外字母v两条对角线连接的时候也有超过基线的部分,虽然很少,但也是降部。(以上信息来自维基百科『降部』词条)
远嚣 Comment