Friday, February 04, 2011

How to crash Delphi compiler in four easy steps

Step one

Start Delphi XE.

Step Two

Create simple project.

program F2048;

uses
Classes,
StreamEnh;

type
TTest = class(TStream)
end;

begin
end.

Step Three

Create unit StreamEnh.

unit StreamEnh;

interface

uses
SysUtils,
Classes;

type
TGpStreamEnhancer = class helper for TStream
public
procedure BE_WriteDWord(const dw: cardinal);
procedure BE_WriteHuge(const h: Int64);
end;

implementation

procedure TGpStreamEnhancer.BE_WriteDWord(const dw: cardinal);
begin
end;

procedure TGpStreamEnhancer.BE_WriteHuge(const h: Int64);
begin
BE_WriteDWord(Int64Rec(h).Hi);
BE_WriteDWord(Int64Rec(h).Lo);
end;

end.

Step Four

Rebuild.

Expected: Program should compile.

Reality: [DCC Fatal Error] F2048.dpr(1): F2084 Internal Error: C10343

Funny things happen if you don’t restart the Delphi. Try recompiling: [DCC Fatal Error] F2048.dpr(9): F2084 Internal Error: O826

Workaround

Change BE_WriteHuge to use a temporary variable:

procedure TGpStreamEnhancer.BE_WriteHuge(const h: Int64);
var
a: int64;
begin
a := h;
BE_WriteDWord(Int64Rec(a).Hi);
BE_WriteDWord(Int64Rec(a).Lo);
end;

Be aware though that you have to restart Delphi if you want the fixed code to compile. Otherwise you’ll be getting Internal error O826.

QC

Reported as QC #91327. Vote for it!

12 comments:

  1. After an internal compiler error, you MUST restart the Delphi IDE, because it causes the IDE compiler subsystem to end in an unstable state.

    ReplyDelete
  2. Anonymous14:48

    Not true.
    After an internal compiler error, you MUST install Delphi 7 again... and you are happy again ;-)

    ReplyDelete
  3. and what if you just remove the const from the parameter in that routine?

    ReplyDelete
  4. Delphi7, this is a joke?

    ReplyDelete
  5. @vv75: Doesn't help.

    ReplyDelete
  6. Xepol19:08

    Delphi 7 had its share of internal compiler errors that required restarting the IDE for stability again.

    ReplyDelete
  7. it would be nice if I could actually vote... "exception, vote limit exceeded" -- WTF?!!
    Embarcadero is pushing the envelope very hard...

    ReplyDelete
  8. Anonymous18:50

    Just a thought, but what if you make the temporary variable (a) an absolute of the parameter?

    procedure TGpStreamEnhancer.BE_WriteHuge(const h: Int64);
    var
    a: int64 absolute h;
    begin
    BE_WriteDWord(Int64Rec(a).Hi);
    BE_WriteDWord(Int64Rec(a).Lo);
    end;

    ReplyDelete
  9. Anonymous18:53

    sorry, typed that wrong :-

    procedure TGpStreamEnhancer.BE_WriteHuge(const h: Int64);
    var
    a:int64rec absolute h;
    begin
    BE_WriteDWord(a.Hi);
    BE_WriteDWord(a.Lo);
    end;

    Of course, you are at the mercy of the format of int64 and int64rec always being compatible.

    ReplyDelete
  10. @Anonymous: That works too.

    ReplyDelete
  11. How irresponsible.... hadn't you heard? Absolute is "holding the language back".

    ;)

    ReplyDelete
  12. Anonymous12:43

    Pfft. It's stuff like this which makes delphi great. Better than that c# rubbish by a mile :-P

    ReplyDelete