Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Все, что вы не знали, но хотели бы узнать о Delphi: Начало. Ошибки В Дельфи


Сначала моя рассылка может показаться бесполезной   и скучной, но обещаю, что со временем она станет интереснее.

Некоторые материалы на английском языке –  заранее извиняюсь =)

Раздел: Начало

Уважаемый подписчик,

О чем будет следующий раздел - решать вам.

Варианты:

Язык программирования Delphi

VCL

Системные функции и Winapi

Базы данных

Работа с файловой системой

Репортинг, работа с принтером

Работа с сетью, Интернетом, протоколами

Работа с графикой, мультимедиа

Ваши предложения высылайте на

formyreferal@rambler.ru

 

В этом выпуске:

Delphi Run-Time Error Codes

Как мне избавиться от выскакивающего окна CPU при ошибках?

Duplicate resource error

Data segment too large error

Error reading symbol file

Stack Overflow, Runtime error 202

Список префиксов Internal Error

Почему возникает ошибка Access Violation?

Как перехватить сообщение об ошибке?

Как предотвратить утечки памяти при возникновении ошибок?

Delphi Run-Time Error Codes

 


Delphi's online help documentation seems to miss the run-time error codes. I usually looked them up in my old Borland Pascal for Windows help file - now they are here for fast access:

1   Invalid function number   
2   File not found   
3   Path not found   
4   Too many open files   
5   File access denied   
6   Invalid file handle   
12   Invalid file access code   
15   Invalid drive number   
16   Cannot remove current directory   
17   Cannot rename across drives   
100   Disk read error   
101   Disk write error   
102   File not assigned   
103   File not open   
104   File not open for input   
105   File not open for output   
106   Invalid numeric format   
200   Division by zero   
201   Range check error   
202   Stack overflow error   
203   Heap overflow error   
204   Invalid pointer operation   
205   Floating point overflow   
206   Floating point underflow   
207   Invalid floating point operation   
210   Object not initialized   
211   Call to abstract method   
212   Stream registration error   
213   Collection index out of range   
214   Collection overflow error   
215   Arithmetic overflow error   
216   General protection fault   


Как мне избавиться от выскакивающего окна CPU при ошибках?

 


HKEY_CURRENT_USER\Software\Borland\Delphi\4.0\Debugging 

ViewCPUOnException=0

 

Duplicate resource error

 


When I try to add a resource to my project's .res file, I get a
"Duplicate Resource" error when linking. The resource I have
added is a unique resource. How can I successfully add the
resource to my project?


The projects resource file is generated by the IDE wizard,
and is not intended to be modified. To add additional resources
to your project, create a separate resource file with a unique
name that does not conflict with either the project or any of
the unit names. Then to add the resource file to
Delphi, simply
add the following line to any unit file in the project:

{$R MyRes.Res}

(where MyRes.Res is the name of the resource file).

To add the resource to Borland's C++ Builder, add the resource
from the project manager.

Data segment too large error

 


When I add a large number of typed constants to my application,
my data segment grows too large. How can I get around this?


Typed constants are added to the Program's data segment. Untyped
constants are added to the code segment of the application only if
they are used. Unless you are going to reassign the value of a typed
constant, you should use an untyped constant instead. Typed constants
should be replaced with initialized variables to be compatible with
future versions of the compiler.

Example:

{This adds the constant to the data segment}
const SomeTypedString : string = 'Test';
const SomeTypedInt : integer = 5;

{This adds the constant to the code segment if used}
const SomeUnTypedString = 'Test';
const SomeUnTypedInt = 5;

Error reading symbol file

 

 

This usually occurs when you move a project to another drive or
directory. Simply deleting the project's .DSM and .DSK files should
remedy the situation.

Stack Overflow, Runtime error 202

 

 

Simply put, stack overflows are caused by putting too much on the
stack. Usually, they are caused by recursive procedures that never
end. A good example would be creating an event handler for the TMemo's
onChange event, and making a change to the Memo during the processing
of the event. Every time the OnChange event gets fired, another change
is made, so the OnChange event gets fired again in an almost endless
loop. The loop finally ends when the stack overflows, and the
application crashes.

Here is an example of a recursive procedure:

procedure RecursiveBlowTheStack;
begin
  RecursiveBlowTheStack;
end;

Sometimes, a stack overflow is caused by too many large procedures.
Each procedure calls another procedure, until the stack simply
overflows. This can be remidied by breaking up large procedures into
smaller ones. A good rule of thumb in regard to a procedures size is
if the procedure's source code takes up more than a screen, its time
to break it down into smaller procedures.

Finally, stack overflows can be caused by creating very large local
variables inside a procedure, or passing a large variable by value to
another procedure. Consider the passing of string variables. If the
string is 255 characters (plus the length byte), if passed by value,
you are actually taking up 256 bytes off the stack.
If the procedure
you are calling passes the string by value to yet another procedure,
the string now takes 512 bytes of stack space. Passing the string (or
other variable) as a var or const parameter takes only 4 bytes, since
var and const parameters are simply pointers to the actual data. You
can also create large variables on the heap by dynamic allocation of
the memory;

The following code demonstrates two procedures BlowTheStack(), and
NoBlowTheStack(). The BlowTheStack procedure attempts to allocate a
large local variable designed to be large enough to crash the
application. The NoBlowTheStack() procedure allocates the same large
variable but allocates it on the heap so the function will succeed.

type
  PBigArray = ^TBigArray;
{$IFDEF WIN32}
  TBigArray = 
array[0..10000000of byte;
{$ELSE}
  TBigArray = 
array[0..64000of byte;
{$ENDIF}

procedure BlowTheStack;
var
  BigArray : TBigArray;
begin
  BigArray[
0] := 10;
end;

procedure NoBlowTheStack;
var
  BigArray : PBigArray;
begin
  GetMem(BigArraysizeof(BigArray^));
  BigArray^[
0] := 10;
  FreeMem(BigArraysizeof(BigArray^));
end;

Finally, the following code demonstrates creating procedures that
accept large variables 
as parameters. The PassByValueAnCrash()
procedure is designed to crash since the value parameter is too large
for the stack. The PassByVar(), PassByPointer(), and PassByConst will
succeed, since these procedures only use 
4 bytes of stack space. Note
that you cannot modify a parameter passed 
as constas a const
parameter 
is assumed to be read only.

Example:

procedure PassByValueAnCrash(BigArray : TBigArray);
begin
  BigArray[
0] := 10;
end;

procedure PassByVar(var BigArray : TBigArray);
begin
  BigArray[
0] := 10;
end;

procedure PassByPointer(BigArray : PBigArray);
begin
  PBigArray^[
0] := 10;
end;

procedure PassByConst(const BigArray : TBigArray);
begin
  ShowMessage(IntToStr(BigArray[
0]));
end;

Список префиксов Internal Error

 


Иногда выскакивают ошибки типа "Internal Error SY424", вот расшифровка префиксов:

B : debugger
BC : debugger
BR : browser
C : codegen
CM : command line version of the compiler
D : parser
DB : debugger
DBG: debug info output
DM : IDE version of the compiler
E : parser
EO : debugger/evaluator
FN : filename / pathname parsing
GH : HPP generator
I : code generator
IN : inspectors
L : linker
LI : BPI file writing
LO : object file loading
M : memory allocation
MA : name mangling
MB : multi-byte (MBCS) support
O : object (OMF) file handling
P : package managment
R : resource writing
S : scanner
ST : standard procedure handling
SY : symbol table
T : code generator
TI : RTTI generator
U : parser
UD : IDE version of the compiler
UI : error handling
URW: DCU reading/writing
W : Object file (OMF) writing
X : code generator

 

Почему возникает ошибка Access Violation?

Previous  Top  Next


Ошибка "Access Violation" возникает, когда идёт обращение к памяти к которой обращение запрещено. Это возможно во многих случаях, но наиболее типичные ситуации я попытаюсь перечислить:

1) Обращение к не созданному объекту.

var e:TEdit;
begin
  e.text:='Hello
 world!';
end;

В данном случае объект e ещё не создан и идёт обращение к памяти, которая ещё не выделена.


2) Обращение к уже разрушенному объекту:

var e:TEdit;
begin
  ...
  e.free;
  ...
  e.text:='Hello
 world';
end;

Тут есть хитрость, допустим вы хотите проверить есть ли объект и модернизируете код:

if e<>nil then e.text:='Hello world!';

или

if assigned(ethen  e.text:='Hello world!';

Особенно часто приходится такое делать когда
надо уничтожить объект:

if e<>nil then e.free;

Так вот - такой код может быть источником ошибки, так как метод Free автоматически не устанавливает указатель в Nil. Обязательно после каждого Free используйте установление указателя в nil:

e.free;
e:=nil;

3) При выходе за границы динамического массива обычно генерится ошибка "Index out of bound", но возможно и возникновение Access Violation, особенно когда не стоят опции компилляции для проверки границ массивов. Эта ошибка может быть очень сложна в отлаживании - дело в том что допустим у вас есть массив а длиной в 10 элементов, в пишете:

a[20]:=something;

И эта строка может пройти как и надо, без всяких проблем, но её выполнение повредит какой-то другой код, причём каждый раз другой! Теперь самая безобидная операция типа i:=10 может вдруг внезапно дать Access Violation.

3) На форме на onCreate вызывается что-то с других форм - эти другие формы на этот момент еще не созданы

4) На форме на onDestroy вызывается что-то с других форм - эти другие формы на этот момент уже разрушены

Как отловить ошибку?

 


Try

  
{здесь вы пишите код в котором может произойти ошибка}
Except
  
{здесь вы пишите код который выполнится если ошибка произойдёт, если ошибки не будет то этот код не выполняется}
End

В
от как будет выполнятся код:
[Line 1]
Try
  [Line 
2]
  [Line 
3]
  [Line 
4]
Except
  [Line 
5]
End
[Line 
6]

Допустим что [Line x] это строка какого-то Вашего кода. Предположим что при выполнении [Line 3] произошла ошибка, тогда программа будет выполнять строки:

1-2-3(ошибка!)-5-6

Е
сли ошибки нет то будут выполнятся следующие линии кода:


1-2-3-4-6


Если надо чтобы ошибка произошла, но перед этим Вы хотите выполнить некие свои действия, то организовать это можно следующим способом:

Try
  
{здесь вы пишите код в котором может произойти ошибка}
Except
  
{здесь вы пишите код который выполнится если ошибка произойдёт, если ошибки не будет то этот код не выполняется}
  raise;// вызвать вновь ту же ошибку
End

Как перехватить сообщение об ошибке?

 


Try
  
{здесь вы пишите код в котором может произойти ошибка}
Except
  on e:Exception 
do Shwomessage(e.message);
End
 

Как предотвратить утечки памяти при возникновении ошибок?

 


Используйте конструкцию

Try
  
{здесь вы пишите код в котором может произойти ошибка}
Finally
  
{здесь вы пишите код который выполнится в любом случае - хоть произойдёт ошибка, хоть нет}
End

Н
апример, это часто применяется во избежание утечек при динамическом распределении памяти:

t:TStringList;
...
t:=TStringList.create
//распределили память под объект t
Try
  
{здесь работаем с переменной t}
Finally
  t.free;
//память выделенная под объект t всегда будет освобождена 
End


В избранное