EditCompiling my Delphi application causes "Internal Error", what does this mean?
Compiler Messages Expert (Delphi 6.0 only)Before I get started, I've written a Delphi 6.0 expert that provides additional help on Delphi compiler messages which is available
here. This expert will not resolve compiler message rather it will simply provide you with additional information which may be useful in resolving the error/hint/warning message. The expert provides help on over 33 different kinds of compiler messages. Please link to this page or others on this site and let people know that this expert is available.
Delphi 7.0 has this feature built-in and is available by selecting View | Additional Compiler Info from within the IDE.
EditInternal Errors Explained
Occasionally when compiling an application in Delphi compilation will halt with an error message that reads "Fatal: Internal Error: X1234" (this is just an example). The error is indicative of a bug in the compiler where it encountered a programming construct that prevents further compilation. Although you likely found a bug in the compiler it's unlikely to be a true show stopper and in nearly all cases it is possible to find an alternative solution short of waiting for Borland to release a compiler patch/update. You're best bet is to start looking for the cause of the problem and then identify potential solutions.
EditWhat does the error message tell me?
While the error message seemingly means very little to the end user it may contain information useful to Borland to help track down the problem. The message "Internal Error" indicates that the compiler has encountered a condition, other than a syntax error, that it cannot successfully process and therefore compilation is aborted. The information following "Internal Error" is usually one to three characters immediately followed by a number which indicates the compiler source file and line number within that file where the error occurred. Because the error represents a file and line number there is no complete listing of all possible internal error messages but typically they fall into one of two categories:
- Problems related to deleting old .DCU/.DCP files and rebuilding your application
- Problems related to coding constructs which the compiler fails to compile correctly and will require changes to your code in order to workaround.
In almost every case there exists a plausible workaround for the error and many times it comes down to methodically eliminating the possible causes to resolve the problem.
EditWhat to do when you encounter an "Internal Error"
- If the error occurs immediately after you have modified code in the editor go back to the spot where you made your changes and make a note of what was changed.
- If you can undo or comment out the change and recompile your application successfully it is possible that the programming construct that you were using exposes a problem with the compiler so jump down to step 7. If not try, the next few steps to resolve your problem.
- Delete all of the .DCU and .DCP files associated with your project.
- Close your project completely using File | Close All, then reopen your project, this will clear the unit cache maintained in the IDE. Alternatively you can simply close the IDE and restart.
- Another option is to try and rebuild your entire application using the Project | Build option so that the compiler will regenerate all of your DCUs.
- If the error is still present exit the IDE and try to compile your application using the command line version of the compiler (dcc32.exe) from a command prompt. This will remove the unit caching of the IDE from the picture and could help to resolve the problem.
- If the problem still exists go back to the place where you last made modifications to your file and review the code.
EditConfiguring Delphi to avoid possible Internal Errors
There are a few steps you can take to avoid situations where you have compiler generated .DCU/.DCP files that are out-of-date. Create a single directory where all of your .DCP files (precompiled package files) are placed. For example, create a directory called C:\DCP and under Tools | Enviroment Options select the Library tab and set DCP output directory to C:\DCP. This setting it will help ensure that the .DCP files the compiler generates are always up-to-date which is particularly useful when you move a package from one directory to another. Similarly I suggest creating a .DCU directory which can easily be done on a per-project basis from the Project Options dialog by selecting Project | Options and clicking the Directories/Conditionals tab and setting the Unit output directory. The key here is that you always want to be using the most up-to-date versions of your .DCU and .DCP files otherwise you may encounter internal errors which are easily avoidable.
EditIdentifying code that causes internal errors
Typically, most internal errors that are not related to out-of-date .DCU/.DCP files typically occur as a result of syntax or constructs that are rather unusual or unexpected (as illustrated below) and can frequently be reproduced with only a few lines of code. If this is the case you can try modifying the code in question to do the same thing but in a different way. For example, if you are typecasting a value try declaring a variable of the cast type and do an assignment first.
Like this:
1 begin
2 if Integer(b) = 100 then...
3 end;
4
5 var
6 a: Integer;
7 begin
8 a := b;
9 if a = 100 then...
10 end;
Here is an example of unexpected code which can be corrected by the developer to resolve the error:
1 var
2 A : Integer;
3 begin
4 { Below the second cast of A to an In64 is unnecessary,
5 removing it can avoid an Internal Error. }
6 if Int64(Int64(A))=0 then
7 end;
EditTechniques for Resolving Internal Errors
Here are some ways to try and resolve internal errors:
- If error seems to be on code contained within a while...do loop try using a for...do loop instead or vice versa.
- If it uses a nested function or procedure (a procedure/function contained within a procedure/function) try "unnesting" them.
- If it occurs on a typecast look for alternatives to typecasting like using a local variable of the type you need.
- If the problem occurs within a with statement try removing the with altogether.
- Try turning off compiler optimizations under Project | Options | Compiler (a rather last resort option) and remember if necessary you can use the {$O-} compiler directive to turn optimizations off for small blocks of code and not the entire project. See the documentation for usage information on this directive.
EditWhen all else fails
Typically there are many different ways to write any single piece of code which you can use to your advantage when trying to resolve an internal error and while this may not be the best solution it may help you to continue work on your application. For example, you can change a "for" loop to a "while" loop or vise versa. Should this resolve the problem it does not mean that either "while" loops or "for" loops are buggy and therefore should be avoided but that perhaps the manner in which the code is constructed, and therefore compiled, has revealed a problem in the compiler. If you've tried your code on the latest release of the compiler and it is still reproducible please create the smallest possible test case to reproduce it and submit it to Borland. If it is not reproducible on the latest version it is unlikely that we will go back and update the version you are using so be creative in looking for ways around the problem!