Introduction

Back in the "good old days", I was primarily working in Borland Delphi, and came across a couple of bugs in the early versions of Delphi.

MMSystem bug

Menu bug

MMSYSTEM bug (Delphi 2.0 and Delphi 3.0)

The definition for TWaveFormat and TPCMWaveFormat are both wrong. In Delphi 2.0 the definitions look like this:

TWaveFormat = record
  wFormatTag: Word; { format type }
  nChannels: Word; { number of channels (i.e. mono, stereo, etc.) }
  nSamplesPerSec: DWORD; { sample rate }
  nAvgBytesPerSec: DWORD; { for buffer estimation }
  nBlockAlign: Word; { block size of data }
end;

TPCMWaveFormat = packed record
  wf: TWaveFormat;
  wBitsPerSample: Word;
end;

We reported the error (described below) to Borland, and in Delphi 3.0 it was changed to:

TWaveFormat = packed record
  wFormatTag: Word; { format type }
  nChannels: Word; { number of channels (i.e. mono, stereo, etc.) }
  nSamplesPerSec: DWORD; { sample rate }
  nAvgBytesPerSec: DWORD; { for buffer estimation }
  nBlockAlign: Word; { block size of data }
end;

TPCMWaveFormat = record
  wf: TWaveFormat;
  wBitsPerSample: Word;
end;

Note the moved moved packed keyword! The problem is, that these structures is used in wav-files and avi-files and the alignment must be one (ensured by a #pragma pack(1) in the original c-headers from Microsoft). Interesting enough, Borland C++ 4.0 and 4.5 also have this error (I do not have BC 5.0 so I don't know). The correct code is:

TWaveFormat = packed record
  wFormatTag: Word; { format type }
  nChannels: Word; { number of channels (i.e. mono, stereo, etc.) }
  nSamplesPerSec: DWORD; { sample rate }
  nAvgBytesPerSec: DWORD; { for buffer estimation }
  nBlockAlign: Word; { block size of data }
end;

TPCMWaveFormat = packed record
  wf: TWaveFormat;
  wBitsPerSample: Word;
end;

Both records must be packed to ensure correct packing of the records.

This error is actually fixed in Delphi 5.0 (I'm not sure what version fixed it first). The definition still looks like the one in Delphi 3.0, but the compiler now packs the TPCMWaveFormat record, even without the packed keyword – probably because the subrecord (TwaveFormat) is packed!

Menu bug (Delphi 1.0)

The menu attached to the menu-property of the active window does not get destroyed when the program exits. This leads to loss of resources under Windows 3.X. The bug can be verified using Windows debug version or simply by inspecting the menu-handle of the menu - when you re-run the program (without running anything in the meantime) you should get the same handle as in the previous run.

The bug seems to caused by the designer thinking that Windows will clean up this menu automatically (the class-menu is destroyed by Windows) and therefore the menu-handle isn't destroyed when the menu-object is freed. Before exiting the (but after the above check) the menu-property is set to nil which removes the menu and prevents it from getting destroyed.
Fortunately a simple fix exists: As the FormDestroy event gets called before the menu-objects are freed, you can prevent your program from leaking resources by including the following code in the FormDestroy:

procedure MyForm.FormDestroy(Sender : TObject);
begin
  Menu := nil  { Add this line to prevent the resource leak }
end;

This line ensures that the menu-handle is destroyed as it no longer is owned by the active window.
This bug is present in Delphi 1.0 (the version that shipped with Delphi 2.0). In Delphi 2.0 and later it has been corrected.