The Delphi Bug List

Migration


What's on this page?

I want this page to have a list of problems that you encounter when porting applications from Delphi 1 to 32 bit Delphi, and from Delphi 2 to Delphi 3.

Borland claims that 'simply recompiling' your existing code will normally cause no problems. But reality shows that there is quite a number of problems you might encounter; a few of these are mentioned in docs somewhere, but others are mentioned nowhere.

Delphi 1 to 32-bit Delphi

This is what Delphi's help says about it
The color codes indicate in which version(s) of Delphi the bug occurs and what its status is.
Latest update: 11 August 1998
Bug # Delphi versions Description
255 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
See separate section for a piece of code that works fine under Delphi 1, but not under Delphi 2.01. It's very hard to say in what category this bug falls, probably it's the VCL
256 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
There is an undocumented difference between how Delphi 1's Readln handles error conditions and how Delphi 2 and 3 do that
257 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
Delphi 2 adds a statement Application.Initialize to generated .DPR code. Delphi 1 .DPR's don't have this statement; the statement must be added 'by hand', otherwise problems may occur
258 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
The constant LR_LOADREALSIZE seems to have disappeared
259 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
(16 bit) Resource files from Delphi 1 are not accepted by Delphi 2. One must convert them to 32 bit (which isn't difficult, by the way)
260 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
Unit names longer than 8 characters cause problems
261 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
Performance of database applications in Delphi 1 is much better than in Delphi 2.
262 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
Some event types have been changed between Delphi 1.0 and 2.0.
263 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
The declaration of ReportEventA (Windows.pas) has changed
264 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
The base value of TDateTime variables has changed between Delphi 1.0 and 2.0.
438 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
Delphi 2 complains when loading forms that were saved with Delphi 3; Delphi 3 does the same with forms created in Delphi 4 (etc?).
395 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 D1 - D2 - SysUtils
The implementation of FileExists has changed: In Delphi 1 it supported wildcards; in Delphi 2 and later it doesn't anymore.
456 1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 D3 to D4 -
property TDataSet.Fields has become read-only

Bug #255; last modified: before April 1998
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
Gotcha Gotcha N/A N/A Unknown Unknown Unknown Unknown

See separate section for a piece of code that works fine under Delphi 1, but not under Delphi 2.01. It's very hard to say in what category this bug falls, probably it's the VCL

Description
Reported by Michael
Here's a problem I ran into porting an app in 1.02 to 2.01. It's based on (stolen from, more like it) something in the first edition of Pacheco & Teixeira's DELPHI DEVELOPER'S GUIDE, a section titled "Subclassing Forms" that begins on p. 540, if you have your copy handy. Basically, the idea is to create "fake" notebook pages out of forms, bringing them up so they fill the area of a panel on your main form. The only essential difference between the book's approach and mine is that they create all their child forms at the beginning and store them in an array of TForm, whereas I, because of the great number of forms involved in the app (too many to admit!), create and free them as needed.
So, the module they call MPGLOBAL.PAS I use unaltered as CHILDFRM.PAS. I've attached as simplified a version of all this as I can come up with. The problem is that, although this works just fine under 1.02, when compiled with 2.01 some strange things happen: (for a full description see the complete bug report).
The source code can also be downloaded: unported.zip.

Michael ends his message with:
In short, then, something(s) got quite screwed up in the translation from 16 to 32 bits, and I haven't a clue as to what it is or what the best way around it might be; and part of the reason I'm letting you in on this now is that neither does Borland technical support, and they've been looking at it (??) for a week or so.
If you or the Bug List's readers can figure out what's going on, I'd certainly be thankful -- and it's probably a terrific bug, too!

So, Delphi'ers around the world: who beats this challenge?


Bug #256; last modified: before April 1998
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
Gotcha Gotcha N/A N/A Unknown Unknown Unknown Unknown

There is an undocumented difference between how Delphi 1's Readln handles error conditions and how Delphi 2 and 3 do that

Description
Reported by Jacques Nomssi Nzali; checked by Duncan Murdoch
There is an undocumented difference between how Delphi 1's Readln handles error conditions and how Delphi 2 and 3 do this.
When doing a ReadLn on a text file, all Delphi versions generate an IO error if the text in the file can't be converted to the numeric value being read. However, in D1, the ReadLn aborts at the first error. In D2 and D3, as many tokens as arguments to ReadLn are first read, and then the conversions are attempted. The result is that the different versions files read different amounts when comments are inserted in a mostly numeric file.
Step-by-step instruction on how to re-produce the problem:
Compile and run the code below. (It should be set as a console app in D2 and D3). The data file and results are shown following it:
program _01read;
uses
  sysutils
  {$ifdef ver80}
  ,wincrt
  {$endif}
  ;
var
  i,j : integer;
  infile : text;
begin
  assign(infile,'_01read.dat');
  reset(infile);
  while not eof(infile) do
  begin
    {$i-} readln(infile,i,j); {$i+}
    if ioresult <> 0 then
      writeln('Error reading line')
    else
      writeln('Read values ',i:3,j:3);
  end;
  readln;
  close(infile);
end.
Use this data as _01read.dat (the semicolons will cause parsing errors):
;
1 1
2 2
3 3
;
4 4
5 5
6 6
To produce this output in D2 and D3:
Error reading line
Read values   2  2
Read values   3  3
Error reading line
Read values   5  5
Read values   6  6
and this output in D1:
Error reading line
Read values   1  1
Read values   2  2
Read values   3  3
Error reading line
Read values   4  4
Read values   5  5
Read values   6  6
Solution / workaround
Don't rely on ReadLn to handle conversion errors; read the lines as strings, and parse them yourself.

Bug #258; last modified: before April 1998
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
N/A Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha

The constant LR_LOADREALSIZE seems to have disappeared

Description
Posted on the DDJ-thread

If you look up LoadImage in the Win32 Reference you'll find this and the other related constants.
This is used in a Delphi 2 build components that had only WinTypes and WinProcs in its uses statement and has always worked fine. Does anyone know where these contants are defined? I've searched my entire Delphi 3 directory and it appears not to exist.
Brad Stowers solved this one:
I've no idea why, but the constant name has changed to LR_VGACOLOR in Delphi 3 (WINDOWS.PAS) from LR_LOADREALSIZE in Delphi 2.

Bug #260; last modified: before April 1998
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
Gotcha Gotcha N/A N/A Unknown Unknown Unknown Unknown

Unit names longer than 8 characters cause problems

Description
In previous versions of Borland Pascal, it was allowed that unit names had more than 8 characters. Of course, the filenames were not longer; they were the first 8 characters of the unit name. In Delphi 1 this was still the case, although it is no longer possible to create a unit with a longer name in the Delphi IDE. But now in Delphi 2.0, in an operating system that allows long file names, long unit names in the uses clause are not associated with file names of 8 characters anymore.
Solution / workaround
Rename the files (to let them have a filename equal to the unit name) or the units (truncate to 8 characters).

Bug #261; last modified: before April 1998
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
Gotcha Gotcha N/A N/A Unknown Unknown Unknown Unknown

Performance of database applications in Delphi 1 is much better than in Delphi 2.

Description
Reported by Ronald Paauwe
With the release of Delphi 2.0, a performance gain of 200% to 300% was promised, compared to Delphi 1.0. But after having converted a 16 bit Delphi application (which uses the BDE) to 32 bits (just recompiling the source and replaced some components with their 32 bit counterparts), it turned out that the application had become a factor 2 to 3 SLOWER. At the Borland helpdesk the problem was known, and they referred to the 2.01 upgrade, in which this problem should be solved. However, after having installed the 2.01 version, nothing seems to have changed: the application is still much slower than compiled with Delphi 1.
The helpdesk's advice to run the application on an NT machine and use a machine with more RAM has been tried, but this also doesn't help!

Bug #262; last modified: before April 1998
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
Gotcha Gotcha N/A N/A Unknown Unknown Unknown Unknown

Some event types have been changed between Delphi 1.0 and 2.0.

Description
For instance, the OnGetText events of TTable and TQuery have¨ changed their "var Text" parameter from "OpenString" to "String" (meaning AnsiString, because VCL is compiled in the $H+ state).
This change causes all kinds of problems. I try to keep a singe source code base for both the 32-bit and 16-bit versions of my application.
Solution / workaround
I tried to overcome the problem of the changed parameter-type like this (follow hyperlink)

Bug #263; last modified: before April 1998
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
N/A Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha

The declaration of ReportEventA (Windows.pas) has changed

Description
Reported by Ezio Vernacotola
From Delphi 3.0 Windows.pas:
function ReportEventA(hEventLog: THandle; wType, wCategory: Word;
  dwEventID: DWORD; lpUserSid: Pointer; wNumStrings: Word;
  dwDataSize: DWORD; 
  lpStrings, lpRawData: Pointer): BOOL; stdcall;
From delphi 2.x windows.pas:
function ReportEventA(hEventLog: THandle; wType, wCategory: Word;
  dwEventID: DWORD; lpUserSid: Pointer; wNumStrings: Word;
  dwDataSize: DWORD; 
  var lpStrings: PAnsiChar; lpRawData: Pointer): BOOL; stdcall;
The parameter lpStrings was "var" in D2 and not in D3.

Bug #264; last modified: before April 1998
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
Gotcha Gotcha N/A N/A Unknown Unknown Unknown Unknown

The base value of TDateTime variables has changed between Delphi 1.0 and 2.0.

Description
Reported by Franz-Leo Chomse
In Delphi 1, DateTimeToStr(1) = '01-01-0001' whereas in Delphi 2, DateTimeToStr(1) = '31-12-1899'.
1. Due to this change a direct transfer of TDateTime values (via file or message) between a Delphi 1.0 application and a Delphi 2.0 application is impossible.
2. Since the fractional part of a TDateTime value is always treated as absolute value, (compatibility with Microsoft OLE datetime stamps), negative mixed date and time values have some weird reactions:
a) date and timevalues of the same day are sorted descending for negative and ascending for positive values.
b) Values between 0.0 and 1.0 are no longer time only values if used in DateTimeToStr. c) the values 0.5 and -0.5 have the same string representation.

Bug #438; last modified: 22-Jul-98
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
Unknown Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha

Delphi 2 complains when loading forms that were saved with Delphi 3; Delphi 3 does the same with forms created in Delphi 4 (etc?).

Description
To reproduce:
In Delphi 4: Create a new application with one form and a button on it. Save this project. Exit Delphi 4; start Delphi 3 and load the project. An error message comes up: "Error reading Form1.OldCreateOrder. Property does not exists. Ignore the error and continue? Note: Ignoring the error may cause components to be deleted or property values to be lost."
The same happens with forms made in Delphi 3 and loaded in Delphi 2; the missing property there is Font.Charset.
However, in all cases I've seen it is safe to simply ignore this error.

Bug #395; last modified: 13-Apr-98
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
N/A Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha Gotcha
D1 - D2 - SysUtils

The implementation of FileExists has changed: In Delphi 1 it supported wildcards; in Delphi 2 and later it doesn't anymore.

Description
Reported by Nikola Dimitrov
To verify: Just call 'FileExists(D:\Directory\*.*)', where 'D:\Directory' directory really exists and really has file(s). The function will return 'false'.
Technically this is not a bug, because the documentation does not say or imply that FileExists supports wildcards, but: Although it may seem that supporting wildcards is not important for FileExists, Delphi 1's FileExists DOES support them. The above mentioned function call returns 'true'.
It appears that the implementation of FileExists has been changed in version 2.0.
Solution / workaround
I wrote a function which calls FileExists. Only if the latter returns 'false', some additional test is made:
function MyFileExists(FileMask: TFileName): boolean;
const
  CST_FileAttr:Word=faAnyFile-faVolumeID-faDirectory;
var
  SearchRec :TSearchRec;
begin
  Result:= FileExists(FileMask);
  If not Result then
    begin
    Result:= FindFirst(FileMask,CST_FileAttr,SearchRec)= 0;
    SysUtils.FindClose(SearchRec);
    end;
end;{MyFileExists}

Bug #456; last modified: 11-Aug-98
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02
N/A N/A N/A N/A N/A Gotcha Gotcha Gotcha
D3 to D4

property TDataSet.Fields has become read-only

Description
Reported by Reinier Sterkenburg
In Delphi 3's db.pas, the property TDataSet.Fields is declared as follows:
    property Fields[Index: Integer]: TField read GetField write SetField;
In Delphi 4's db.pas, this reads as follows:
    property Fields: TFields read FFields;
Besides that this property has become read-only, the type has also been changed. The new type TFields has another property Fields which more or less plays the role of the old Fields property, but this one is also read-only:
    property Fields[Index: Integer]: TField read GetField; default;
So in old code, occurrences of Fields[xxx] must be replaced with Fields.Fields[xxx]. And if you were assigning to it, you're still stuck.

Index page
The Delphi Bug Lists are maintained by Reinier Sterkenburg, with help from the DeBug Team.
All feedback is appreciated. See also the feedback section of the Delphi Bug List home page.