Your application will be shut down!
Page 1 : What access violations are and how to prevent AVs at design-time.
Access Violation, General Protection Fault or Invalid Page Fault, the name changes, but the nature of the error is always the same. Access Violation is a phrase that users of personal computers see when an application they are running tries to access storage that is not designated for their use - and crashes.
Access violation at address <HEX_value>
in module <Application.Exe>.
Read of address <HEX_value_2>
If Windows applications were able to write outside of its assigned storage area, it could overwrite other applications' or the operating system's instructions and data. If that should happen, the operating system would "crash" or close down in some way and you would have to reboot the operating system. For example, when a program error occurs in Windows NT/2000, Dr. Watson steps in and stops the program, taking some quick diagnostic stats, recording them in a text file.
Access Violations are some of the most frustrating errors encountered in Windows programming. The purpose of this article is to help you find the solution to your AVs with Delphi. To start with, access violations have nothing to do with Microsoft Access.
We can divide AVs encountered while developing with Delphi in two major types: runtime and design time.
Access Violations at Design-Time
Design time AVs are experienced when starting and closing the Delphi IDE or building a Delphi project.
Hardware
AV messages that crop up while your computer is in operation can be generated by various different sources, including the system BIOS, the operating system or hardware driver routines. Some video, sound or network cards can actually cause AVs in Delphi. Why? Every card in your machine comes with device drivers. Depending on the manufacturer, the version of Windows, and the version of Delphi used you may experience problems. There are some steps that can be taken to help resolve these issues:
· Take the steps necessary to verify that there are no conflicts between your installed devices.
· Sometimes lowering the resolution will help stabilize a quirky video card driver.
· Insure that if you are using a dual processor motherboard that the step revision for each processor is the same.
· Always use the latest driver for all of the components in your system.
Software
Although Windows is the most popular operating system for Intel machines, due to the extreme fragility and bugginess of Windows, misbehaving applications can readily crash the OS (and the OS sometimes crashes itself spontaneously). There are ways that you can help your chances of having a more stable programming environment, which in turn will help to prevent certain AVs.
· Although Windows 9X is quite popular, Windows NT/2000 has proven to be a much more stable environment for almost all Windows coding platforms.
· Ensure that you have installed the latest service packs for NT/2000. With each service pack released, you will find that your machine will become more stable.
· One excellent method of proactive error prevention is to always keep the current with all updates and patches for whatever edition and version of Delphi (BDE, ADO, ...) that you are using. Always have the latest patch for Delphi - the number of AVs, especially design time violations, will drastically decrease.
· If you are getting random access violations in the IDE, you have most likely installed a bad component or package or a wizard that was not written/compiled for your Delphi version. Try uninstalling custom components one by one (or package by package) until the problem goes away, then get in touch with the component vendor regarding this issue.
· Check to see whether if there is anything unusual installed on the machine with the program that crashes. Curious shareware utilities and beta products are AV favorites.
· An access violation can also occur because a system setting is wrong. If you repeatedly encounter the same error message, record the details and call the company that makes the software that seems to be causing the message.
That is all I can suggest for design-time access violations, the rest of the article deals with run-time AVs and how to make sure your application will not cause them!
Your application will be shut down!
Page 2 : The most common run-time Delphi access violations and how to prevent them.
It happens with any software development: you write the application, test it, and send it out into the wide world. Then a user calls up to tell you that your pride and joy has fallen flat on its face.
You might want to consider compiling your application with the {$D} compiler directive - Delphi can create map files which can be a big help in locating the source of AV errors. The Project Options dialog box (Project|Options|Linker & Compiler) lets you specify all you need. For units, the debug information is recorded in the unit file along with the unit's object code. Debug information increases the size of unit file and takes up additional memory when compiling programs that use the unit, but it does not affect the size or speed of the executable program. The Include debug info (Project|Options|Linker) and Map file (Project|Options|Linker) options produce complete line information for a given module only if you've compiled that module in the {$D+} state.
Access violations usually manifest themselves in only one aspect of the program. It is important to think about what the user was doing when the problem first occurred, and then work towards a solution from there. From the user's point of view, your application has made the user stop working, and the time spent telling you about the problem seems to be delaying you from fixing it. However, talking with the user is the only way you will find the problem and improve your application.
Now you will see how to easily find the exact routine, source code file, and line where an AV occurred when given nothing more than the crash address.
'Search - Find Error...'
When a run-time AV occurs, the error message your user gets, looks something like:
Access violation at address <HEX_value>
in module <Application.Exe>
Read of address <HEX_value_2>
If you have your application compiled with debug information in the Delphi IDE, you can locate the line of source code corresponding to the compiled code that caused the access violation.
Non-existing object
One of the most common causes of AVs in Delphi programming is the use of an object that has not yet been created. If the second address is FFFFFFF (or 0000000) you can almost bet you are accessing an object that has not been created. For example calling a method on a form that was not auto-created and is not instantiated by the code.
procedure TfrMain.OnCreate(Sender: TObject);
var BadForm: TBadForm;
begin
// this will generate an AV
BadForm.Refresh;
end;
Suppose that BadForm is listed in the "Available Forms" list in the Project Options window - forms that need to be created and freed manually. In the code above the call to Refresh method of the BadForm form causes an access violation.
If you have enabled the "Stop on Delphi Exceptions" in the Language Exceptions tab on the Debugger Options window than the following message pops up:
The message states that the EAccessViolation has occurred. The EAccessViolation is the exception class for invalid memory access errors. This is what you will see while developing your application. The next message box will see the user - and the program will die:
Access violation at address 0043F193
in module 'Project1.exe'
Read of address 000000.
The first hex number ('0043F193') is the address of the runtime error in the compiled code (Project1.exe) were the AV occurred. In the IDE choose menu option 'Search|Find Error...', enter the address at which the error occurred ('0043F193') in the dialog and click OK. Delphi will now recompile your project and show you the line of source code were the runtime error occurred, that is, the BadForm.Refresh.
What follows is a list of the most common causes of AVs in Delphi development. This list is not, and it can't be, intended to cover all the situations in which an AV can occur. Please post your AV to the Forum - we'll try to solve them together - real life examples are normally more obscure than those that follow.
Calling a non-existing object
As stated above the most probable cause of AVs is the use of an object that has not yet been created or has already been destroyed. To prevent this kind of AV, be sure than any objects you refer to, have first been created. For example, you might be opening a Table in the form's OnCreate event when the Table component is located on a data module which has not been created yet (was removed from the auto-crete forms list).
In the next code an AV occurs after calling a method on an object (b:TBitmap) that has already been destroyed.
var b:TBitmap;
begin
b:=TBitmap.Create;
try
//do something with b
finally
b.free;
end;
...
//this will cause an AV - b does not longer exist
b.Canvas.TextOut(0,0,'this is an Access Violation');
end;
Invalid API parameter
If you attempt to pass an invalid parameter to a Win API procedure an AV might occur. The best way to solve this kind of AV is to refer to the Win API help for information on the particular API call and the parameters and parameter types it expects. For example, always be sure not to pass an invalid pointer to a buffer parameter.
Let Delphi Free
When an object ownes another object, let it do the deleting. Since, by default, all forms (autocreated) are owned by the Application object, when the application terminates, it frees the Application object, which frees all forms. For example, if you have two forms (Form1/Unit1 and Form2/Unit2) both autocreated when the application starts, the next code will result in an AV:
unit Unit1;
...
uses unit2;
...
procedure TForm1.Call_Form2
begin
Form2.ShowModal;
Form2.Free;
Form2.ShowModal; //AV
end;
Killing the exception
Never destroy the temporary exception object (E). Handling an exception automatically destroys the exception object. If you destroy the object yourself, the application attempts to destroy the object again, generating an access violation.
Zero:=0;
try
dummy:= 10 / Zero;
except
on E: EZeroDivide do
MessageDlg('Can not divide by zero!',
mtError, [mbOK], 0);
E.free. // causes an access violation
end;
Indexing an empty string
An empty string has no valid data. Therefore, trying to index an empty string is like trying to access nil and will result in an access violation:
var s: string;
begin
s:='';
s[1]:='a'; //AV
end;
Dereferencing pointers
You must dereference the pointers, otherwise you are moving the address of the pointers and possibly corrupting other memory locations.
procedure TForm1.Button1Click(Sender: TObject);
var
p1 : pointer;
p2 : pointer;
begin
GetMem(p1, 128);
GetMem(p2, 128);
{This line may cause an access violation}
Move(p1, p2, 128);
{This line is correct}
Move(p1^, p2^, 128);
FreeMem(p1, 128);
FreeMem(p2, 128);
end;
That's all folks
I hope that now, your users will scream less about how your application crashed.
Random access violations in the IDE
Delphi used to work fine but now I get random access violations in the IDE! Why?
You most likely installed a bad component or package that was not written/compiled for Delphi 4. Try uninstalling custom components one by one (or package by package) until the problem goes away, then get in touch with the component vendor regarding this issue. 2/0 / 998 2:59:06 PM