2
votes

I've just updated my Indy10 installation to the latest revision (5260) and I now get an error when trying to compile a Windows service that receives emails from an email server.

[DCC Error] IdGlobal.pas(8657): F2084 Internal Error: C4963

Reverting back to revision 5239 doesn't cause an issue.

The issue seems to be in IdGlobal.ReadLnFromStream on line 8633:

LBufSize := ReadTIdBytesFromStream(AStream, LBuf, LBufSize);

I'm wondering if this is a 64-bit issue, has anyone else encountered this issue? I'm using Delphi 2007 on Windows 7 Professional x64.

1
FYI, line 8633 is LBufSize := IndyMin(LStrmSize - LStrmPos, LBUFMAXSIZE); The line you quoted is line 8634 instead. So which line is the actual problem? The only thing I can think of is that both lines do involve Integer<->Int64 conversions, but I can't imagine the compiler choking on that, especially if it was working previously. - Remy Lebeau
But either way, although there have been a lot of changes to IdGlobal.pas in the past 2 months (mostly in preparation for iOS 64bit), none of the changes should be affecting ReadLnFromStream() like this. But this is an internal error, which means anything could potentially be putting the compiler into a bad state even before it reaches ReadLnFromStream(). I don't have D2007 installed, so I can't troubleshoot the problem myself. If you can narrow down a fix, you can send it to me for checkin. - Remy Lebeau
Out of curiosity, does the error still occur if you change this line: LBufSize := IndyMin(LStrmSize - LStrmPos, LBUFMAXSIZE); to this: LBufSize := Integer(IndyMin(LStrmSize - LStrmPos, LBUFMAXSIZE));? Or change ReadTIdBytesFromStream() to use Integer instead of TIdStreamSize? - Remy Lebeau
@RemyLebeau - the LBufsize is declared as integer, ReadTIdBytesFromStream expects a TIdStreamSize, but calls a class method which expects integer. I think I was looking at 8634, changing the LBufSize to TIdStreamSize fixed it, apologies for any mistakes, I'm now going off memory and the earliest I can do additional testing is Monday morning. - SteB
TIdStreamSize is Int64 in D6+. A dynamic array uses NativeInt for its length and indexing, so Integer on 32-bit systems and Int64 on 64-bit systems. But TStream.Read() uses Longint for its byte count and Longint is 32-bit on most platforms (iOS 64bit is changing that). So maybe ReadLnFromStream() needs to declare LBufSize as NativeInt to match the RTL and avoid unnecessary conversions, even though only 2K are being read at a time? I see some other functions in IdGlobal that are using TIdStreamSize where NativeInt might make more sense. - Remy Lebeau

1 Answers

2
votes

I don't know when and why this changed but I have the same issue (Delphi 2007). it appears that ReadTIdBytesFromStream is expecting an int64 (TIdStreamSize) to be passed as the Count parameter but the variable being passed (LBufSize) is an integer.

This appears to cause the complier considerable problems and it throws an internal error. I browsed around the Indy code until I found other examples of this function call that generated no errors.

I found this snippet of code in the TIdHashIntf.GetHashBytes method and borrowed from it

 repeat
   LSize := ReadTIdBytesFromStream(AStream,LBuf,IndyMin(ASize, 2048));

I then changed the code in ReadLnFromStream from this:

repeat
  LBufSize := IndyMin(LStrmSize - LStrmPos, LBUFMAXSZE);
  LBufSize := ReadTIdBytesFromStream(AStream, LBuf, LBufSize);

to this

repeat
  LBufSize := ReadTIdBytesFromStream(AStream, LBuf, IndyMin(LStrmSize - LStrmPos, LBUFMAXSIZE));

And now Indy builds and complies again.

As far as I can tell this change will not effect anything (apart from fixing the broken build), but I can appreciate it is a bit of a WTF. Without going deep into the reasons as to why some variables are int, others int64 and yet others are TIdStreamSize, this is the best I can do. Maybe Remy could enlighten us all.

Incidentally I noticed if complied in debug mode the fatal complier error did not occur.