Application error access violation in module

В статье рассмотрено, что за ошибка "Access violation at address ... in module", и как её можно исправить разными методами в ОС Windows.

Каждый, кто знаком с ОС Windows знает, что невозможно пользоваться компьютером, не столкнувшись с ошибками и проблемами. Многие из них можно решить обычной перезагрузкой системы. Но встречаются и такие, при которых невозможно продолжить работу. Одной из таких ошибок является «Access violation at address … in module». Читайте далее, как её исправить.Сообщение access violation

Содержание

  1. Причины появления ошибки Access violation at address … in module
  2. Как избавиться от ошибки обращения к памяти
  3. Проверка запуска оболочки Windows
  4. Чистка системного реестра Windows
  5. Другие методы решения ошибки «Access violation at address …»
  6. Восстановление или переустановка системы

Причины появления ошибки Access violation at address … in module

Данная ошибка может возникать, когда процесс обращается не к тому типу памяти или она не предназначена для использования этого приложения. Она может возникать при запуске игр, использовании любых программ или медиа проигрывателей. Этому может способствовать как сбой в самой системе и архитектуре файлов на диске, так и при влиянии вирусного программного обеспечения. Часто еще этот сбой возникает, когда пользователь пытается открыть файл или обратиться к нему, но по адресу его нет.

Ошибку могут спровоцировать программы, которые были разработаны неумелыми программистами. Чтобы не сталкиваться с этой проблемой, нужно скачивать программное обеспечение только с официальных сайтов.

Как избавиться от ошибки обращения к памяти

Ошибка появляется при попытке выключить компьютер, перезагрузить его или поменять свой профиль. Но часто так и не удается это сделать из-за системного сообщения. Приходится либо выключить устройство из розетки, либо выключать его долгим нажатием кнопки питания Power. Перед тем, как устранять ошибку Access violation at address … in module, проверьте хранилище вирусов вашего антивирусного программного обеспечения. Возможно некоторые файлы, к которым вы пытались обратиться, были помещены сюда. Такие данные для системы будут уже не доступны.

  1. Чтобы это сделать, найдите значок на панели задач (трее) в виде стрелочки, нажмите её и появятся скрыты значки.
  2. Здесь выберите значок антивируса ПКМ.
  3. В контекстном меню обычно находится пункт «Карантин».

Пункт Карантин

Выберите его и проверьте содержимое. Если найдете там файлы программ, которым вы доверяете — удалите их из карантина. Если ошибка Access violation at address продолжается, необходимо переустановить данную программу и внести в антивирусе в список доверенных.

После этого попробуйте перезапустить компьютер и войти в ОС через последнюю удачную конфигурацию.

  1. Для этого при появления начального экрана нажмите клавишу F8 и не отпускайте до тех пор, пока не появится окно с несколькими способами запуска.
  2. Выберите «Запуск последней удачной конфигурации».
  3. В этом случае будет использована система с конфигурацией драйверов и реестра, которые работали до этого стабильно.

Пункт последняя удачная конфигурация

Выберите последнюю удачную конфигурацию в Windows

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

Проверка запуска оболочки Windows

Следующим шагом в исправлении ошибки Access violation at address … in module будет проверка запуска оболочки операционной системы.

  1. Откройте окно ввода команд — WIN+R.
  2. Введите следующую команду «Regedit» и подтвердите, нажав Enter.
  3. Откроются ветки, здесь выберите HKEY_LOCAL_MACHINE.
  4. Далее найдите ниже SOFTWARE.
  5. Здесь отыщите ветку Microsoft, ниже выберите Windows NT и CurrentVersion.
  6. И наконец выберите Winlogon.

Реестр ОС Windows

Когда вы откроете последнюю ветку в правой части появится окно со списком ключей и параметров, найдите здесь Shell. Его необходимо открыть как обычную папку, дважды нажав мышью. В исправной системе здесь должно быть значение Explorer.exe. Если у вас стоит иное — исправьте его и сохраните изменение. Точно так же нужно проверить ключ Userinit. Здесь по умолчанию установлено C:windowssystem32userinit.exe. Если здесь указано что-то другое — исправьте. Далее выйдите из редактора и закройте все окна. Перезагрузите компьютер и проверьте, появляется ли ошибка.

Чистка системного реестра Windows

В некоторых случаях при ошибке Ошибка Access violation at address in module помогает очистка системного реестра.

  1. Для этого вполне сгодится программ CCleaner, которую можно скачать по ссылке https://www.ccleaner.com/ru-ru.
  2. Загрузите и установите её.
  3. Откройте и выберите слева «Реестр».
  4. Нужно активировать внизу «Анализ», далее появится кнопка «Очистить».

Программа CCleaner

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

Другие методы решения ошибки «Access violation at address …»

Далее нужно попытаться восстановить файлы, которые возможно были удалены самим пользователем, антивирусами или вирусам. Для этого понадобится дистрибутив с текущей операционной системой Windows. Вставьте его в привод и следуйте дальнейшей инструкции:

  • выберите внизу рабочего стола «Пуск» и введите в поиске «Командная строка»;
  • в результатах выберите её ПКМ и нажмите «От имени администратора»;
  • в черном окне введите «sfc /scannow» без кавычек.Команда sfc

Будет произведена проверка файлов на жестком диске. Эта команда сканирует файловую систему жесткого диска и, если находит сбои в системных файлах автоматически исправляет их. Компьютер будет перегружен в процессе. Если этот способ снова не помог вам устранить проблему «Access violation at address … in module», попытайтесь вернуть рабочую систему при помощи точек сохранения.

  1. Снова откройте меню «Пуск», выберите поисковую строку и введите «Восстановление».
  2. В результатах найдите «Восстановление системы» — выберите его.
  3. Выберите пункт, который запустит восстановление.Окно восстановления системы
  4. В следующем окне нужно будет выбрать точку, которую система создала ранее.
  5. Выберите её и подтвердите свои действия.

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

  1. Выберите кнопку «Пуск», затем найдите справа раздел «Панель управления».
  2. В следующем окне отыщите «Восстановление или удаление программ».
  3. В списке найдите проблемное ПО и выберите кнопку «Удалить» на панели инструментов или в самом блоке (в зависимости от версии ОС).Adobe Creative Cloud в списке программ
  4. Далее вам нужно снова установить ПО из дистрибутива.

Восстановление или переустановка системы

Если ни один из методов вам не помог решить эту ошибку, попробуйте сделать восстановление с участием диска Windows.

  1. Для этого вставьте в привод диск и перезагрузите компьютер.
  2. Войдите в настройки подсистемы BIOS и выберите загрузку с дисковода.
  3. Перезагрузите компьютер и активируйте загрузку с оптического диска.
  4. После того, как будут установлены временные файлы, вы увидите окно, где предлагается переустановить систему с несколькими вариантами. Выберите «Восстановление системы».
  5. Далее найдите необходимое восстановление и нажмите «Готово».

Когда будет выполнено восстановление, проверьте наличие ошибки на компьютере. В том случае, если она снова возникает, придется переустановить Windows. Это можно сделать, не затрагивая файловый раздел жесткого диска. Это значит, что вы можете переустановить только систему на диске C:, а другие диски, где обычно хранятся файлы пользователя не трогать. После переустановки системы вы точно избавитесь от ошибки Access violation at address … in module.

What is an Access Violation

Every computer program uses memory for running. Memory is consumed by every variable in your program. It can be form, component, object, array, record, string or simple integer. Memory can be allocated automatically for certain types of variables (such as integer or static arrays), the other types require manual control of memory (for example, dynamic arrays). Essentially, from the point of operating system, each variable is characterized by its address (i.e. — location) and size.

Roughly speaking, program uses 3 «types» of memory: area for global variables, the stack and the heap.

Memory for global variables is allocated by OS loader when executable module is loading and it is freed when module is unloading. Global variables are those, which declared outside of class or any routine. The stack is used for allocating memory for local variables (which are declared in some function or procedure) and auxiliary data (such as return addresses or exception handlers). The heap is used for storing dynamic data (such as objects, dynamic arrays, strings, etc.).

Note, that for variables of dynamic types (such as dynamic arrays, strings, objects or components) — though the variable itself is stored in global area or stack, but its data is always allocated on the heap and it (often) require manual control.

Regardless of who allocates memory for the variable (you manually, or the compiler automatically), memory for each variable must be allocated before its using, and later (when the variable is no longer needed) it should be freed.

Sometimes there can be a situation, where your application trying to get access to certain memory location, which wasn’t allocated or was already released — due to bugs in your code. When such things happens — the CPU raises an exception of class EAccessViolation. The usual text for this error is as follows: «Access violation at address XXX in module ‘YYY’. Write/read of address ZZZ». Though there is the one simple reason for this kind of error, the real situations for it can be very different.

Looking for source code line of Access Violation

So, what should you do with access violation? Well, first you should try to identificate a source line in your code, where it appears.

If you are getting EAccessViolation while running under debugger:

A typical debugger’s notification about access violation exception

Then you should just click «Break» (it is called «Ok» in older Delphi’s versions) and the debugger will point you to source line immediately. Additionally you can take a look at call stack by choosing View/Debug Windows/Call stack from Delphi’s main menu:

A typical call stack as displayed by IDE debugger

This window shows you a call stack — the trace of executing to current code’s point. You should read this from top to bottom. The current location is marked by little blue arrow. You can also double-click on line to go to a particular location. For example, if you double-click on «Unit12.Test» line — debugger will show you location where exception was raised.

If you are using an exception tracer tool (such as EurekaLog) then there would be a bug-report instead of usual error message. You can see a call stack in the report (call stack view can differ due to different building algorithm):

A typical EurekaLog report about exception

You can see there the same information. And you also can double-click on lines to go to that locations in IDE code editor.

Okay, finding the error’s location — this is only half of the case. Determination why there is an error in this line — it is the second half of the case.

Looking for the Access Violation’s reason by analyzing the code

If you got an error while using debugger, then it is quite simple — you should place a breakpoint to your problem-line and check all variables and expressions in this line after breakpoint’s hit — and here it is, the reason for access violation. Just use the debugger.

If there is only a bug-report — then you should use your telepathic abilities to find out the truth. Those psychic powers are comes with experience and we can help you a little with it — by giving you a list of most common mistakes, which can lead to EAccessViolation exceptions.

1. First, there are all kinds of errors of accessing an array’s element outside of its borders. For example, the typical newbie’s mistake can look like this:

var
  X: Integer;

  for X := 1 to Length(List) do // wrong! Should be: for X := 0 to Length(List) — 1 do
  begin
    // … do something with List[X]
  end;

So, if your problem line contains [] — there is a good reason to validate your expression inside [].

Usually, you should catch errors of this sort at development/testing stage by using «Range Check Errors» option. The point is that such errors are very dangerous, because they may go unnoticed, even more than that — they can destroy the stack, so that you can not get the location of the error. But more on this later.

2. All kinds of messing with arguments. Usually those are untyped parameters and buffer-overflow errors:

var

  S1: array of Integer;

  S2: String;

  // Wrong:

  Stream.ReadBuffer(S1, 256);     // this corrupts the S1 pointer

  // Correct:

  Stream.ReadBuffer(S1[0], 256);  // this reads data into S1 array

  // Wrong:

  FillChar(S2, Length(S2), 0);            // this damages the S2 pointer

  // Correct:

  FillChar(Pointer(S2)^, Length(S2), 0);  // this clears the S2 string by filling it with zeroes

Usually these errors are catched immediately upon function call. You should just examine a function’s documentation to figure out what you did wrong. Check: what function expects to receive and what actually you give to it.

3. Passing data between modules. Well, newbies likes to pass data (especially String) between exe and DLL, without caring much about two different memory managers in modules.

These errors are usually detected at development time.

4. Wrong declaration of functions, which are imported from DLL. The most common mistake is wrong calling convention. If you are getting EAccessViolation just by calling a function from DLL — just carefully verify its declaration. Be sure, that its signature is correct and you didn’t forget about stdcall or cdecl.

Though these errors usually detected at development stage, there can be cases, when wrong declaration will make it at production code.

5. Missing of proper synchronization, when working with threads. If you are using more than one thread in your application, then there can be troubles. For example, you can not access a VCL objects from another thread as VCL is not thread-safe — you should use Synchronize for this. Actually, the problem is encountered when one thread changes the data, which is used by another thread — and that becomes a complete surprise for the second thread.

Unfortunately, the problems with thread are the most complex ones. They are very hard to diagnose. The best you can do is to guarantee, that such things can not happen. If you are in doubt — place you code in synchronize or guard it by critical section, when working with shared variables. Sometimes programmer uses CreateThread instead of BeginThread or TThread and forgets about changing IsMultiThreaded variable.

6. Calling a function via invalid procedural variable. For example:

var

  Lib1, Lib2: HMODULE;

  Proc: procedure;

  Lib1 := LoadLibrary(‘MyDll.dll’);         // one piece of code loads DLL. It can be in different thread

  Lib2 := GetModuleHandle(‘MyDll.dll’);

  Proc := GetProcAddress(Lib2, ‘MyProc’);   // there is no checks! There can be no function named ‘MyProc’

  Proc;                                     // Proc can be = nil -> there will be an Access Violation

  FreeLibrary(Lib1);                        // some code unloads library

  Proc;                                     // though Proc <> nil, its code is no longer available

                                            // that is why there will be an AV.

The whole case is very similar to the next situation.

7. Calling of methods or any other access of objects/components, which wasn’t created yet or were already released. You should consider this reason if there is some object variables in your problem line of code. Especially, if you do a manual allocate or free of objects somewhere in your program.

The one part of the problem is that when you destroy an object, its variable is not cleared automatically — it continues to point at invalid memory location. The other part is that local variables are not initialized to zero and contains trash at function’s call. The last part: there can be multiple reference to one object/component via different variables. Here are few examples:

var
  Str: TStringList;

  Str.Add(‘S’); // Mistake! We forget to create an object by calling Str := TStringList.Create;

  Str := TStringList.Create;
  Str.Add(‘S’);

  Str.Free; // We destroyed the object, but the Str still points to old location

  if Str.Count > 0 then // Mistake! An access to already released object

All such memory access errors are dangerous as they may be unnoticed. For example, we can access a deleted object, but our memory manager still wasn’t return memory to the system, so our access can be successful.

It’s recommended to use FreeAndNil to destroy objects or (better yet) to use interfaces instead of objects — because interfaces are auto-managed types, which will be released automatically.

The situation with local arrays is even worse: the point is that local arrays are allocated in the stack, so there is large areas of available memory at its borders. To make things worse: this memory is heavily used by application (as oppose to the memory, which were released by the object destruction).

For example:

procedure TForm1.Button1Click(Sender: TObject);
var
  S: array [0..1] of Integer;
  I: Integer;
begin
  I := 2;            // suppose, that I is somehow calculated in you application
                     // and suppose that there is a bug, and I gets wrong value.
  S[I] := 0;         // this line will damage the return address of Button1Click in the stack
end;                 // there will be EAccessViolation at this line, because the address of the caller is lost
 
procedure TForm1.Button2Click(Sender: TObject);
var
  S: array [0..1] of Integer;
  I: Integer;
begin
  I := -6;          // suppose, there is another wrong value.
  try
    S[I]     := 1;  // instead of changing an array, we damages an exception handler frame, which was set by try
    S[I + 1] := 2;
    S[I + 2] := 3;
    Abort;          // there would be a full crash, without any message. 
                    // The exception manager detect a damaged stack and will terminate application immediately
  except
    ShowMessage(‘Aborted’);
  end;
end;
 
procedure TForm1.Button3Click(Sender: TObject);
var
  S: array [0..1] of Integer;
  I: Integer;
begin
  I := -1;          // yes, another invalid value for I
  S[I] := 1;        // we damages the stack again, but there won’t be any EAccessViolation or side effect!
end;

It is very treacherous situation, isn’t it? Depending on how we messed up with the array’s index, we can get:

a). Application, which produces the correct results.

b). Application, which produces the wrong results.

c). Application, which raises an exception.

d). Application, which crashes.

To make things worse: the very same application can display any of the above behavior, depending on external conditions, such as OS and Delphi’s version, user actions before error and so on.

That is why it is extremely important to use «Range Check Errors» option while you develop and testing your application.

Well, you can also enable it for production code, if you isn’t sure that your testing was good enough.

So what exactly should we do with access violation? Well, we have a source line, so we should just look through above mentioned cases and try to apply them to our line of code:

Do we have the [] in our line? If so: can there be an invalid index here?
Are there any work with objects? If so: check the logic — is there a too early object’s release?
Do we use a DLL? If so: is a function declaration correct? Does all dynamic data exchanges properly handle?

There can be a great help if we can also use few hints from the data.

Looking for Access Violation’s reason by analyzing the data

First, we can retrieve some useful information from error’s message itself. Let’s check it out:

Access violation at address XXX in module ‘YYY’. Write/read of address ZZZ.

Okay, the address XXX points to exact location of code, where exception was raised. This is the same address, which is used by Delphi’s debugger and EurekaLog to point you to your line of code. The executable module for this address is also displayed in the error message — as YYY. Usually it is your exe, DLL or some system/third-party DLL. Sometimes, however, there can be cases when XXX do not hold any meaningful value. For example, if there is no YYY in the message of if XXX looks suspicious (less then $400000 or greater than $7FFFFFFF on x86-32), then you definitely have problems either with stack corruption (for example, «c» item from the previous section), of call of invalid function (item 6 or, sometimes, 4 from previous section).

The next useful piece of information is «write» or «read» word. The «write» means that the exception occurred during writing, the «read» means that, well, the problem while reading (quite obvious, isn’t it?). That means, that we only need to check write or read parts in the problem source line. For example, if the problem line is «P := W» then we should check P if there was «write» word and check W if there was «read» word in the error’s message. Additionally, «read» may happen if code tries to execute something inaccessible (unloaded DLL, «trashed» procedural variable, or virtual method in a deleted object, etc.).

And the last hint comes from ZZZ. Actually, we do not care about exact value, but rather about if it is small or large. «Small values» are something like $00000000, $0000000A or $00000010. The «large values» are, for example, $00563F6A, $705D7800 and so on. So, if ZZZ is small — then your code tried to access an object via nil reference. If ZZZ is large — then your code tried to access an object via non-nil invalid pointer. In the first case you should check: why do you try to use nil pointer (or who is the bad guy, who set pointer to nil). In the second case you should search for bad guy, who released the object, but doesn’t clear the variable itself.

You can also check if ZZZ matches or is very close to these values:

These are some common debug markers, which are used to fill released memory. If you have marker in your address — it means that you are trying to access unavailable location, which was previously valid. For example, «Access violation at address 0040D18C in module ‘Project1.exe’. Read of address DEADBEE7» could mean attempt to access string field in already deleted object.

A similar issue could be when XXX matches ZZZ exactly. This means that some code tried to call function/method via a pointer (e.g. like procedural variable or virtual method), and that pointer was invalid/corrupted. E.g. a call via «trashed» pointer. For example, procedural variable to unloaded DLL, virtual method of already deleted object, etc. The culprit is immediate caller of this rogue location, e.g. second line in the call stack. Such bug can manifest itself in 5 possible ways:

1. If EurekaLog’s memory debugging is not disabled (default), and memory for pointer was not reused/overwritten — EurekaLog will trigger «Application tries to call a virtual method of already deleted object» error;
2. If EurekaLog’s memory debugging is disabled, or memory for pointer was reused/overwritten:
a. Code may call an invalid location, which will immediately crash with «Access violation at address X. Read of address X». The important part is that both addresses are exactly the same. The culprit will be immediate caller of that location (e.g. second line in call stack);
b. Code may call a valid location. E.g. trashed pointer happens to point to some random code in application. If you are lucky — this will crash immediately with access violation (two addresses will be different). If you are unlucky — execution may continue for some time. Some other routines may be called. Eventually:
i. Execution may crash with arbitrary exception (it may be access violation, it may be not access violation);
ii. Execution may complete «successfully» (e.g. without any exception at all). Your application may behave weirdly, or there could be no visible effect at all. You may not even notice the bug.

Apart from error’s message, there can be another information, which comes from assembly and CPU tabs in EurekaLog’s bug-report.

You can see the assembly listing of your program on the «Assembler» tab. It is provided here only for convenience — that way you do not have to search it somewhere else. This is no additional information there. But on the «CPU» tab — you can see the status of CPU’s registers, (part of) the stack and (part of) the memory at the moment of exception raising.

For example, we can look at the assembler listing and see that the problem line involves, say, EAX and EDX registers. We can check that EAX is 0 on CPU tab, which means that we are trying to assign value via nil pointer. Then we take a look at the line of source code, which we learned from the call stack, and we will know the name of the variable. And here’s the reason for you: the variable, used in assignment, was = nil.

Of course, to work with this information you need a minimum knowledge of assembler, but it is a quite powerful tool.


Send feedback…
Build date: 2022-03-28
Last edited: 2020-01-23


PRIVACY STATEMENT
The documentation team uses the feedback submitted to improve the EurekaLog documentation.
We do not use your e-mail address for any other purpose.
We will remove your e-mail address from our system after the issue you are reporting has been resolved.
While we are working to resolve this issue, we may send you an e-mail message to request more information about your feedback.
After the issues have been addressed, we may send you an email message to let you know that your feedback has been addressed.

Permanent link to this article: https://www.eurekalog.com/help/eurekalog/eaccessviolation.php

You are here: Home / Windows / Exception Access Violation In Windows 10 – How To Fix ?

Some Windows 10 users have recently reported an error, where they cannot run a particular application or run a code in a module, and get an error code where the message reads “Exception Access Violation”.

Here I shall discuss why you may get this error, and how you can solve it using the solutions provided below.

exception_access_violation

Contents

  • 1 Am I Facing The ‘Exception Access Violation’ Error?
  • 2 How To Fix Access Violation At Address In Module?
    • 2.1 Solution 1: Run The Hardware Troubleshooter
    • 2.2 Solution 2: Turn Off Data Execution Prevention For That App
    • 2.3 Solution 3: Reinstall The Application
  • 3 Conclusion

Am I Facing The ‘Exception Access Violation’ Error?

The Exception Access Violation error can show up on any application. The main reason why you get this error on your device is because the access to protected memory address was denied by your operating system to the application. This can become very annoying as this error prevents you from launching any application on your device.

How To Fix Access Violation At Address In Module?

There are three possible ways in which you can solve the access violation error on your Windows device. Here I shall discuss these easy steps with which you can solve this error on your system.

Solution 1: Run The Hardware Troubleshooter

The hardware troubleshooter was included by Microsoft in Windows 10 to identify and solve any potential issues with your hardware. This is a powerful tool, which can identify most of the sources of the issues that your device is suffering from, hampering your user experience.

With Windows 10 v1809, the Hardware troubleshooter was removed from the settings app, citing unpopularity among users. There is, however, another way to launch the Hardware troubleshooter.

  1. Open a Run dialog by pressing the Win + R
  2. Type the following command in the Run dialog and press Enter to launch the hardware troubleshooter:
    %systemroot%system32msdt.exe -id DeviceDiagnostic

device_diagnostic

  1. Follow the on screen instructions to identify and solve the error on your device.

hardware_troubleshooter

If the Exception Access Violation sai error was being caused by some malfunctioning hardware, this should solve the error on your Windows 10 device.

Solution 2: Turn Off Data Execution Prevention For That App

The Data Execution Prevention (DEP) is a security feature in Windows 10 that can help prevent damage to your computer from viruses and other security threats. This is a very useful feature that can help prevent various damages to your device which can be caused by these harmful software.

Harmful programs can try to attack Windows by attempting to execute code from the system memory, which is reserved for Windows and other system files. If any other application emulates this, the DEP feature will block running of the said app, and you will get the error message, ‘Exception Access Violation’.

Follow these steps to turn off Data Execution Prevention:

  1. Open This PC and click on System Properties.
  2. Under the Advanced tab, locate the Performance
  3. Here, click on Settings.

system_properties

  1. Click on Data Execution Prevention
  2. Choose “Turn on DEP for all programs and services except those I select”.

turn_on_dep_except

  1. Click Add, browse to the installation folder of the troubled Kindle app, and locate the .exe file.
  2. Set an exception and confirm changes.

Solution 3: Reinstall The Application

If none of the solutions provided above helped you, some corrupt application file may be causing the error on your device. This is also true if you are on the beta version of the application, as the beta version is prone to bugs and is known to be full of errors.

If you have not updated to the latest version, update your app after deleting the old files. To do this, you can make use of third party batch uninstallers like IObit uninstaller.

Then download the latest version of the application from the official website for the application. Double click on the downloaded installer package to install the file. Your error should be resolved.

Conclusion

So there you have it. With the solutions provided above, you should now be able to solve the issue if you faced the error message that says,’ Exception Access Violation’. Tell us in the comments below how you solved the error on your device, and to discuss further the same.

Критическая ошибка, она же более известна как «синий экран смерти», всегда влечёт за собой определённые последствия, так как её возникновение свидетельствует о том, что в работе операционной системы возникли серьёзные неполадки. Каждый пользователь, являющийся оператором компьютера, так или иначе, но сталкивался с проявлением подобной проблемы и знает, что далеко не всегда её решение лежит на «поверхности». Порой для исправления возникшей ситуации приходится прибегать к крайним мерам – это фактическая переустановка операционной системы Windows. Стоит ли применять данный способ в решении рассматриваемой в настоящей статье ошибки, в чём заключаются причины её возникновения. Обо всём об этом вы сможете прочитать ниже.

Как исправить ошибку Access violation

Исправление ошибки Access violation.

Причины и решения

Такой универсальный вариант (переустановка ОС) уже давно является наиболее рекомендуемым на различных IT-форумах, а также некоторыми «специалистами» воспринимается как «панацея» от любых проблем, что, конечно же, не отвечает действительности. Да, справедливости ради стоит отметить, что полная чистая переустановка Windows практически гарантированно решит имеющиеся программные проблемы, но ни в коем разе не аппаратные. Поэтому не стоит спешить «сносить» операционную систему, для начала следует определить причинно-следственную связь и только после этого принимать подобные кардинальные решения. Итак, рассматриваемая ошибка «Access violation» сигнализирует о том, что какой-либо процесс при обращении к нужному ему типу памяти встречается с трудностями. Например, при запуске игрового программного обеспечения процесс пытается обратиться не к свойственному ему типу памяти, вызывая при этом упомянутую выше ошибку, которая сопровождается текстовым сообщением в виде «Access violation at address № in module «…dll. Write of address…».

Ошибка Access violation

Причин возникновения подобной ситуации может быть очень много, что серьёзно усложняет определение причинно-следственной связи, поэтому и применяемые методы носят комплексный характер, а именно:

  1. Проведите полную проверку операционной системы на наличие вирусной активности. Не прибегайте исключительно к услугам штатного антивируса, а обратите своё внимание на сторонние утилиты, к примеру, «DoctorWeb Curelt», «Malwarebytes» и «Adwcleaner». Проверьте всё тесно связанное с работой компьютера, включая внешние устройства хранения информации, которые подключались ранее к компьютеру, так как не исключено, что основная «зараза» засела именно там.
  2. Проверьте операционную систему на целостность компонентов, для этого:

Процесс сканирования и внесение правок может быть продолжительным, но прерывать функционирование утилиты не рекомендуется. Дополнительно после завершения работы «sfc/scannow» можно обратиться к помощи команды «dism.exe /online /cleanup-image / restorehealth», инициировать работу, которой можно с помощью той же командной строки. Сканирование диска командой

  1. Также будет не лишним проверить используемые жёсткие диски и/или твердотельные накопители и наличие битых секторов, ошибки. Для этого подойдёт хотя бы штатная утилита «CHKDSK». Проверка утилитой диска

Вышеизложенные рекомендации носят обобщённый характер, так как их применение обосновано не только при возникновении каких-либо проблем в работе операционной системы, но и как профилактические меры по поддержанию качества функционирования Windows. Если ошибка не нашла своего решения и продолжается «терзать» пользователя, то следует прибегнуть к более точечным проверкам, которые заключаются в следующем:

  1. «Проверка реестра»:

Также будет не лишним прибегнуть к функционалу программы «CCleaner» для проверки реестра на ошибки. Основную проблему это может не решить, но добиться улучшения общего состояния операционной системы вполне реально.

  1. «Проверка корректности используемого драйверного обеспечения». Откройте «Диспетчер устройств» и удостоверьтесь, что все компоненты полностью работоспособны и среди них нет неизвестного устройства, которое было бы помечено жёлтым треугольником с восклицательным знаком внутри. Дополнительно можно обратиться к специализированному софту и проверить актуальность всех используемых драйверов.
  2. «Проверка качества работы программного обеспечения». Если рассматриваемая проблема проявилась при открытии какой-либо программы или игры, то попробуйте полностью удалить их и установить заново, но удостоверившись в том, что возможности вашего компьютера, а также версия операционной системы соответствует техническим требованиям продукта. Если игра была получена не совсем «честным/законным» путём, то попробуйте скачать другой репак или сменить основной источник. Если вы уверены в том, что вирусного программного обеспечения нет и проблема проявляется в отдельно взятом программном обеспечении при любых манипуляциях с ним, то можно попробовать внести данное ПО в список исключения DEP, для этого:

Перезагрузите компьютер и проверьте качество работы Windows и работоспособность нужной вам программы/игры.

 Заключение

К сожалению, как видно из всего представленного выше, в рассматриваемой ошибке нет каких-то конкретных причин возникновения. «Access violation», как и её собратья, является лишь следствием каких-либо сбойных моментов в работе Windows, поэтому и все приведённые рекомендации направлены на восстановление штатной работы OS. Всё сказанное в начале про переустановку Windows таковым и остаётся и в завершении статьи.

Иногда при запуске игры или программы возникает ошибка Access violation at address, которая сообщает о проблеме на стороне прав доступа. Но это вовсе не означает, что действуют какие-то ограничения. Причем неважно в каком виде она появилась:

  • read of address 00000000
  • in module
  • write of address
  • the bat
  • Или каком-то другом. Это все одно и то же.

В переводе на русский означает «Нарушение доступа по адресу». Но что это за проблема и как ее исправить? Давайте разбираться.

Содержание статьи

  1. Диагностика памяти
  2. Чистый запуск
  3. Удаление программ
  4. Сканирование на предмет ошибок
  5. Проверка системных компонентов
  6. Редактирование DEP
  7. Выключение UAC
  8. Другие способы решения
  9. Комментарии пользователей

Диагностика памяти

Первый шаг — запустить диагностику памяти. Есть два способа, как это сделать:

  1. Универсальный, используя утилиту Memtest.
  2. Для пользователей Windows 10 и 8. Разберем его подробнее.

В строку поиска вводим слово «памяти» и запускаем средство.

сканирование памяти

Выбираем первый пункт с пометкой «рекомендуется». Система перезагрузится и начнется сканирование.

Дождитесь завершения процедуры и посмотрите на графу «Состояние». Ошибок быть не должно. При их наличии выньте ОЗУ и протрите контакты ластиком, затем установите обратно. Если это не поможет, то замените старые планки новыми.

Чистый запуск

Предлагаю запустить компьютер в чистом режиме, чтобы узнать, не вызывает ли проблему одна из установленных программ.

Для этого:

  1. Введите msconfig в строке «Выполнить», комбинация «WIN + R».msconfig команда
  2. Переместитесь в «Службы» и скройте все от «Майкрософт». Отключите оставшиеся.отключение служб
  3. Проделайте то же самое в разделе «Автозагрузка».чистка автозагрузки
  4. Перезагрузите компьютер.

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

Удаление программ

Как говорил ранее, ошибку Access violation at address могут вызывать некоторые приложения. Чаще всего это fl studio, Artmoney, txdworkshop. Поэтому удалите лишние через деинсталлятор «Your Uninstaller» или любой другой. Желательно это делать из безопасного режима.

Если в безопасный режим войти не удается, то откройте диспетчер задач «CTRL + SHIFT + ESC», во вкладке «Процессы» найдите нужную утилиту и правым щелчком мыши откройте ее расположение. После этого удалите процесс.

skype в диспетчере задач

Теперь, находясь в этой папке удалите содержимое.

Если приложение нужно, то попробуйте переустановить его. Предварительно очистив Windows утилитой «Ccleaner».

Сканирование на предмет ошибок

Некоторые системные файлы могут отсутствовать или быть повреждены. Желательно проверить это и исправить. Делается в автоматическом режиме с помощью команд в командной строке.

DISM /Online /Cleanup-Image /RestoreHealth – нужен доступ в интернет.

sfc /scannow

dism online

Напишите их и нажмите после каждой «Enter». По завершении перезапустите ПК.

Проверка системных компонентов

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

Будьте осторожны при редактировании реестра, неправильные действия могут нарушить работу ОС. Действуйте четко по инструкции.

Для этого:

  1. Войдите в редактор через «WIN + R» — regedit.regedit
  2. Перейдите по пути HKLMSOFTWAREMicrosoftWindows NTCurrentVersionWinlogon и найдите два параметра: Userinit и Shell. Дважды щелкните по каждому из них. Убедитесь, что в графе «Значение» указаны правильные пути. При необходимости измените их.shell и userinit в реестре

Shell (должен ссылаться на исполняемый файл) – explorer.exe

Userinit (должен ссылаться на исполняемый файл) — C:Windowssystem32userinit.exe

По окончании перезапустите компьютер.

Редактирование DEP

Возможно, ошибку Access violation at address (in module, read of address) вызывает компонент «DEP», блокирующий в целях безопасности некоторые программы. В качестве решения предлагаю внести приложение в список исключений.

Как это сделать:

  1. Откройте «Свойства» ярлыка «Компьютер».свойства значка компьютер
  2. Перейдите в «Дополнительные параметры».дополнительные опции
  3. Во разделе «Дополнительно» щелкните по «Параметры» быстродействия.конфигурация быстродействия
  4. Зайдите в «Предотвращение выполнения» и активируйте последний параметр с пометкой «кроме выбранных ниже». Укажите нужное приложение через кнопку «Добавить».добавление exe файла в исключения dep

Выключение UAC

Большинство приложений разработанных на базе Java не работают из-за включенного контроля учетных записей, сокращенно «UAC». Давайте выключим его.

  1. Откройте классическую «Панель управления».
  2. Войдите в раздел «Учетный записи».учетные записи
  3. Щелкните по изменению контроля.настройка контроля для пользователя
  4. Передвиньте ползунок вниз до появления пометки «Никогда не уведомлять».режим без уведомлений

Другие способы решения

Если ничего не помогло, то предпримите следующие действия.

Помните, что Вы можете рассчитывать на мою помощь. Для этого напишите мне в комментариях.

Примечание для людей, заходящих сюда из поисковика: эта статья написана для разработчиков программ. Если вы не программист и не пытаетесь исправить ошибку в СВОЕЙ программе, эта статья — не для вас. До свидания. Извините, что потратил ваше время.

Примечание для студентов/новичков, пишущих на Delphi/C++ Builder: эта статья написана для диагностики исключений в вашей программе. Если вместо этого вы получаете ошибки от самой IDE (а не от вашей программы), например, access violation в пакете dclite60.bpl, то эта статья — не для вас. Чтобы решить проблемы с IDE — идите сюда. Краткий ответ: не надо использовать динозавров (Delphi 5/6/7), используйте современные IDE (Delphi XE и выше). Если всё же хочется динозавров, то часто причиной является DEP. Т.е. нужно добавить Delphi/Builder в исключения DEP. Ну или на крайний случай — отключить/удалить конфликтующий пакет.

Итак, для всех прочих (а именно: разработчиков Delphi/C++ Builder, пытающихся решить проблему возникновения исключения Access Violation в своей программе) — приступим!

Исключение класса EAccessViolation — это самое частое исключение в Delphi-программах. Я хотел бы рассмотреть, что это такое, когда возникает, и как с ним бороться. Этот пост скорее для начинающих, поэтому данные могут излагаться с упрощением.

Примечания:

  • если вы совсем начинающий или студент/студентка и получили Access Violation — первым делом включите опцию Range Check Errors (Project/Options, вкладка Compiler) и сделайте Project/Build.
  • если вы плохо или совсем не понимаете, что такое указатели и/или объекты — рекомендую сначала прочитать эту статью.
  • если вы плохо или совсем не умеете работать с отладчиком IDE (или даже не знаете, что это такое) — прочитайте сначала эту статью.

Каждая программа использует при работе память (*). Память занимает любая переменная в вашей программе. Будь это форма, компонент, массив, запись, строка или же простой Integer. Под некоторые переменные память выделяется автоматически (например, под переменные типа Integer и статические массивы), под другие — вы должны выделять её сами, явно (например, динамические массивы). Собственно, с точки зрения операционной системы каждая переменная характеризуется адресом в памяти (местоположением) и размером. Понятно, что обычно данные разных переменных не пересекаются — за исключением случаев обращением к одной области памяти через разные имена с помощью указателей.

Грубо говоря, обычно в программе используется три типа памяти: область памяти для глобальных переменных, стек и куча.

Память для глобальных переменных выделяется загрузчиком ОС при загрузке исполняемого модуля программы в память и освобождается при выгрузке модуля (выходе из программы). Глобальные переменные — это любые переменные, объявление которых располагается вне класса или процедуры. Стек используется для размещения локальных переменных (объявленных в процедуре/функции) и служебных данных (типа адресов возврата и адресов обработчиков исключений). Куча же используется для размещения динамических данных.

Подробнее.

Заметим, что для переменных динамических типов данных (динамические массивы, строки, любые объекты, компоненты), хотя сама переменная может размещаться в области для глобальных переменных или в стеке (а, значит, память для неё выделяется автоматически), но данные, на которые она указывает, всегда размещаются в куче и, зачастую, должны управляться вручную.

Вне зависимости от того, кто выделяет память для переменной (вы вручную или компилятор автоматически), память для любой переменной должна быть выделена перед использованием, а потом, когда переменная уже не будет нужна — освобождена.

Иногда из-за ошибок в коде программы происходит ситуация, когда программа при выполнении пытается получить доступ к памяти, которая не была выделена или уже была освобождена. Когда такое происходит, процессор возбуждает исключение класса EAccessViolation. Обычный текст ошибки в приложении Delphi — «Access violation at address XXX in module ‘YYY’. Write/read of address ZZZ» («Нарушение доступа по адресу XXX в модуле ‘YYY’. Попытка записи/чтения в ZZZ»). Хотя причина этого исключения всего одна (попытка обращения к недействительной памяти), но эта ошибка может проявлять себя в весьма разном виде и коде.

Более подробно об указателях и памяти говорится в уже упоминавшейся выше статье.

Ищем место возникновения Access Violation

Как, собственно, бороться с этими ошибками? Ну, если вы получили EAccessViolation под отладчиком:


То нужно просто нажать на «Break» («Ok» в старых версиях Delphi) и отладчик сразу же ткнёт вас на строчку с ошибкой. Также можно посмотреть стек вызовов (в меню Delphi — View/Debug windows/Call Stack):


В этом окне будет показано, как же вы туда попали. Читается это дело сверху вниз (текущее место помечено стрелочкой). Можно дважды щёлкать по строкам в этом окне для перехода в код, соответствующий этой строке.

Иными словами, отладчик сразу же тыркает вас в строку с ошибкой.

Если же вы используете средства автоматической диагностики типа EurekaLog/madExcept, то вместо обычного сообщения об ошибке вы получите баг-отчёт, в котором будет виден тот же самый Call Stack (вид стека вызова может отличаться из-за различных методов его получения):


Не имеет значения, столкнулись ли вы с проблемой во время отладки или получили баг-отчёт от EurekaLog для уже распространяемой программы — хорошо бы подготовиться к этой ситуации заранее и включить опции проекта, упрощающие отладку. Как правило, это опции «Use Debug DCUs» и «Stack frames».

Окей, найти место ошибки — это только пол-дела. Определить почему же в этой строке возникла ошибка — это вторые пол-дела.

Ищем причину возникновения Access Violation анализом кода

Если ситуация возникла у вас в отладчике, то тут всё относительно просто: вам нужно установить точку останова на проблемную строчку и проверить значения всех переменных и выражений, участвующих в ней — вот вам и причина ошибки, находится сразу же. Я не буду подробно останавливаться на теме отладки здесь, более подробно об этом написано в моей статье, часть 2 (осторожно: большой размер).

В случае, если у вас на руках есть только баг-репорт, а не ситуация под отладчиком, то вам придётся использовать свои телепатические способности, которые обычно развиваются с опытом. Дабы помочь вам в этом, здесь я как-раз и хочу рассмотреть типичные причины возникновения ошибки Access Violation.

1. Во-первых, это всевозможные ошибки выхода за границы массивов. Например, типичная ошибка новичка может выглядеть так:

var
  X: Integer;
...
  for X := 1 to Length(List) do // ошибка! Должно быть: for X := 0 to Length(List) - 1 do
  begin
    // ... делаем что-то с List[X]
  end;

Если в вашей проблемной строке есть скобочки типа [], то у вас есть хороший довод к проверке допустимости выражения в [].

Обычно такие ошибки нужно отлавливать на стадии отладки, включая опцию Range Check Errors. Дело в том, что подобные ошибки весьма опасны тем, что могут пройти незамеченными (и потом редко ловятся при эксплуатации программы), даже более того — они могут разрушить стек, так что нельзя будет получить место возникновения ошибки. Но об этом позже.

2. Различного рода неверные передачи параметров. Обычно эти ошибки отлавливаются во время разработки и тестирования, нежели во время эксплуатации программы. Чаще всего они возникают при использовании процедур с нетипизированными параметрами. Сюда же относятся различные варианты ошибок переполнения буфера, например:

var
  S1: array of Integer;
  S2: String;
...
  // Неверно:
  Stream.ReadBuffer(S1, 256);     // портит указатель S1
  // Правильно:
  Stream.ReadBuffer(S1[0], 256);  // читает данные из потока в массив

  // Неверно:
  FillChar(S2, Length(S2), 0);            // портит указатель S2
  // Правильно:
  FillChar(Pointer(S2)^, Length(S2), 0);  // очищает строку, забивая её данные нулями

Для избавления от таких ошибок нужно просто внимательно изучать документацию на функции: что они ожидают увидеть и что вы действительно им подсовываете.

3. Передачи данных между двумя менеджерами памяти. Обычно ошибки такого плана возникают при передаче данных из DLL в приложение или наоборот. а также между двумя DLL. Чаще всего новички любят передавать из/в DLL строки типа String.

Причины этого я рассматривал ранее. Эти ошибки обычно отлавливаются немедленно во время разработки программы и очень редко доживают до рабочей программы. Решаются эти проблемы правильным проектированием.

4. Неверное объявление функций, импортируемых из DLL. Наиболее часто путают модель вызова. Если у вас получается EAccessViolation при вызове функции из DLL — просто внимательно посмотрите на её объявление и убедитесь, что её сигнатура верна — чаще всего пропускают модель вызова, stdcall или cdecl.

Хотя обычно ошибки такого плана отлавливаются на этапе разработки, тем не менее могут быть ситуации, когда ошибка проползает в готовую программу. Вот увлекательная история Реймонда Чена о том, как программа может работать с неверно объявленным прототипом функции (довольно интересны и посты в серии до и после этого).

5. Отсутствие синхронизации при работе с потоками. Если вы делаете программу с использованием нескольких потоков, то у вас могут быть проблемы, если вы не обеспечили необходимой синхронизации. Например, любые обращения к VCL запрещены из вторичных потоков — вам нужно использовать Synchronize. Собственно, проблемы тут возникают, когда один поток меняет данные с которыми работает второй поток — что для последнего становится полной неожиданностью.

К сожалению, ошибки с синхронизацией потоков наиболее тяжело диагностировать. Лучшее, что вы можете сделать — прогарантировать, что такие проблемы никогда не возникнут: используйте Synchronize и/или заключайте код в критические секции при работе с разделяемыми потоками переменными. Иногда проблемы возникают из-за использования CreateThread вместо BeginThread или TThread (из-за отсутствия установки IsMultiThreaded).

6. Вызовы функций или процедур по процедурной переменной, когда она содержит неверное значение. Например:

var
  Lib1, Lib2: HMODULE;
  Proc: procedure;
...
  Lib1 := LoadLibrary('MyDll.dll');         // один код загрузил библиотеку. Быть может - другой поток
  ...
  Lib2 := GetModuleHandle('MyDll.dll');    
  Proc := GetProcAddress(Lib2, 'MyProc');   // нет проверки на ошибку. Функции может не быть - тогда Proc будет равна nil
  Proc;                                     // Proc может быть равна nil - будет Access Violation
  ...
  FreeLibrary(Lib1);                        // ещё какой-то код выгрузил библиотеку
  ...
  Proc;                                     // хотя Proc <> nil, код, на который она указывает,
                                            // больше не загружен - здесь будет AV.

Ситуация очень сильно напоминает следующий пункт и бороться с нею нужно такими же методами.

7. Вызовы методов или любые другие обращения к объектам или компонентам, которые ещё не созданы или же были уже удалены. Подозревать эту причину нужно, когда в проблемной строке у вас участвует переменная-объект или компонент. Особенно, если вы хоть где-то в программе занимаетесь ручным созданием или освобождением компонентов или объектов.

Проблема в том, что при освобождении компонента, его ссылка-переменная не меняется, продолжая указывать на уже удалённую память. Кроме того, локальные переменные не инициализируются автоматически при входе в процедуру и содержат мусор. Вот пример подобного рода ошибок:

var
  Str: TStringList;
...
  Str.Add('S'); // Ошибка! Мы забыли создать объект вызовом Str := TStringList.Create;
  ...
  Str := TStringList.Create;
  Str.Add('S');
  ...
  Str.Free; // Здесь мы удалили объект, но ссылка Str по-прежнему указывает на ту же область памяти
  ...
  if Str.Count > 0 then // Ошибка! Обращение к уже удалённому объекту

Как мы уже говорили ранее, в приложениях Delphi есть служебный код, называемый «менеджером памяти», который отвечает за выделение и освобождение памяти в вашей программе и служит прослойкой между низкоуровневыми функциями операционной системы и вашим кодом. При всей своей пользе менеджер памяти, однако, добавляет в программу одну проблему: из-за него в программе находится куски памяти, которые выделены с точки зрения операционной системы, но свободны с точки зрения программы. Например, удалили вы компонент, но менеджер памяти не отдаёт память системе немедленно, придерживая её для дальнейшего использования.

Поэтому все ошибки доступа к памяти опасны в первую очередь тем, что могут пройти незамеченными. Например, мы обращаемся к уже удалённому объекту, но поскольку менеджер памяти ещё не отдал эту память системе, то обращение может пройти успешно. Чуть ранее мы говорили, что для предотвращения таких ситуаций вам нужно использовать FreeAndNil и другие механизмы. Ситуация ещё хуже с локальными массивами: дело в том, что локальные массивы размещаются в стеке, в котором обычно есть довольно большие участки размещённой памяти по краям массива. Что ещё хуже, эта память обычно реально используется программой (в отличие от памяти, которую мы освободили при удалении объекта), так что вы можете, спокойно промахнувшись, записать что-то не туда, и в итоге, ошибка всплывёт в совершенно другом месте из-за испорченных данных. Чтобы сделать ситуацию ещё хуже: в стеке хранятся и служебные данные программы, необходимые для её выполнения — это адреса возврата и обработчики исключений.

Например:

procedure TForm13.Button1Click(Sender: TObject);
var
  S: array [0..1] of Integer;
  I: Integer;
begin
  I := 2;           // предположим, что это значение как-то вычисляется и
                    // из-за ошибки в программе получает неверное значение
  S[I] := 0;        // эта строка затрёт адрес возврата из Button1Click в стеке
end;                // в этой строке произойдёт Access Violation, т.к. мы испортили адрес возврата

procedure TForm13.Button2Click(Sender: TObject);
var
  S: array [0..1] of Integer;
  I: Integer;
begin
  I := -6;          // пусть мы снова ошиблись в I
  try
    S[I]     := 1;  // вместо массива мы стираем обработчик исключений, установленный try
    S[I + 1] := 2;
    S[I + 2] := 3;
    Abort;          // полный вылет программы, т.к. менеджер исключений обнаружил испорченный стек
  except
    ShowMessage('Aborted');
  end;
end;

procedure TForm13.Button3Click(Sender: TObject);
var
  S: array [0..1] of Integer;
  I: Integer;
begin
  I := -1;          // пусть мы снова ошиблись в I
  S[I] := 1;        // хотя мы снова портим стек, но нам это сходит с рук
                    // никакого EAccessViolation не будет вовсе!
end;

Весьма коварные ситуации, не правда ли? В зависимости от того, как именно мы ошибёмся в индексе массива, мы можем получить (**):
а). Программу, выдающую правильные результаты.
б). Программу, выдающую неверные результаты.
в). Программу, возбуждающую исключение.
г). Программу, вылетающую вообще.
Причём одна и та же программа с таким багом может показывать любое из этих поведений, смотря по тому, на какой машине она запущена и в каких условиях/окружении выполняется.

Вот почему чрезвычайно важно использовать опцию Range Check Errors во время разработки и тестирования.
Ну, вы можете также включить её и для release-версии кода, если не уверены в качестве своей стадии тестирования.

Итак, что, собственно, нужно сделать, когда мы получили Access Violation? Ну, с помощью предыдущего пункта мы находим строку с ошибкой, а дальше пытаемся по пунктам подставить возможные причины:
— Есть в строке []? — подумаем, а не может ли у нас быть неверный индекс?
— Есть работа с объектами? Проследим, какова логика работы — не удаляется ли объект раньше времени?
— Используем DLL? А правильно ли объявлена функция? А уж не обмениваемся ли мы динамическими данными (строками, там, массивами)?
и т.д.

Существенную помощь в таком анализе нам поможет следующий пункт.

Ищем причину возникновения Access Violation анализом данных

Во-первых, мы можем попытаться вытащить информацию из самого сообщения об ошибке. Напомним его вид:

Access violation at address XXX in module ‘YYY’. Write/read of address ZZZ.

Во-первых, адрес XXX указывает на точное место в программе, где произошла ошибка. Именно по этому адресу отладчик Delphi и EurekaLog ищут строчку для показа её вам. Также модуль, которому она принадлежит, показывается в сообщении как YYY. Обычно это ваша программа, DLL или системная DLL. Однако, иногда это может быть и совершенно левое значение. Например, если в сообщении не указан модуль или значение XXX выглядит подозрительно (меньше $400000 или больше $7FFFFFFF), то у вас либо проблемы с перезаписью стека (пункт «в» в конце предыдущего раздела), либо вызов неверной функции (пункт 6 или, иногда, 4 из предыдущего раздела).

Следующий полезный кусок информации — это слово «write» или «read». Первое означает, что возникла проблема при записи информации, второе — что проблема была при чтении. Соответственно, вам нужно проверять в строке кода либо операции записи, либо операции чтения. Например, если проблемная строка была «P := W;«, то вам нужно обратить внимание на P, если в сообщении стоит «write». Если же там стоит «read», то нужно проверять, что же у нас с W.

И последний кусок информации, который можно извлечь из сообщения — это ZZZ. Собственно, точное значение нас обычно не волнует. Важен только факт — велико оно или мало. Мало — это что-то типа $00000000, $0000000A, $00000010 и т.п. Большие значения — это, например, $00563F6A, $705D7800 и др. Если ZZZ мало, то у вас идёт обращение по ссылке равной nil. Если оно велико, то у вас идёт обращение по ненулевой, но мусорной ссылке. В первом случае вам нужно искать, зачем же вы полезли по ссылке равной nil (или кто же освободил переменную раньше времени), во втором случае вам нужно понять, кто же это такой освободил объект, а ссылку не занулил. Короче говоря, это значение (так же, как и с «write»/»read») помогает сузить область поиска.

Помимо сообщения, если у вас есть баг-репорт, вы можете проанализировать значения регистров и состояние памяти. В этом вам помогут две последние вкладки в отчёте EurekaLog:



На первой вкладке вы можете видеть ассемблерный листинг своей программы. Приводится он здесь только для удобства — чтобы не надо было лезть ещё куда-то, чтобы подсмотреть его. Никакой информации он не несёт. А вот на второй вкладке вы можете видеть состояние регистров, (части) стека и (части) памяти в момент исключения. В данном случае мы смотрим на ассемблерный листинг и видим, что в проблемной команде участвуют регистры eax и edx. По вкладке CPU мы находим, что eax равен 0, что означает, что мы пытаемся присвоить значение по указателю, равному nil. Взглянув на строчку исходника, которую мы узнали из стека вызовов, мы узнаем имя переменной. Вот вам и причина: переменная оказалась равна nil.

Конечно, эта работа с такой информацией требует минимального знания ассемблера, но зато и является довольно мощным инструментом.

В следующий раз мы поговорим о ситуациях, когда у вас в коде есть ошибка, но никакого исключения не возбуждается. Частично мы уже говорили об этом здесь (например, пункт «1» и пункты «а»-«б» в конце второго раздела). Но в следующий раз мы пойдём чуть дальше и посмотрим, что ещё можно сделать для отлова таких ситуаций. И, в любом случае, у вас всегда есть возможность переписать код ;)

Читать дальше.

См. также: как читать баг-отчёты.

Примечания:
(*) Очень подробно о памяти для приложений рассказывает Марк Руссинович.
(**) Вот ещё один пример, как один и тот же код может демонстировать широкий диапазон поведений.

2001 г

Ловим баги или Почему программы допускают «недопустимые операции»

Е. Левшаков, В. Ковалев, mcsa.ru

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

«Нарушение Доступа» — фраза, которую пользователи видят, когда приложение делает попытки обратиться к памяти, которая не обозначена для их использования — и как следствие происходит сбой в работе программы:

Access violation at address <HEX_value>
in module <Application.Exe>.
Read of address <HEX_value_2>

Ситуация, при которой Windows давала бы полную свободу программам — записывай данные куда хочешь, скорее всего бы привела к разноголосице программ и полной потери управления над компьютером. Но этого не происходит — Windows стоит на страже «границ памяти» и отслеживает недопустимые операции. Если сама она справиться с ними не в силах — происходит запуск утилиты Dr. Watson, которая записывает данные о возникшей ошибке, а сама программа закрывается.

Известно, что при программировании, особенно крупных программных продуктов, уследить за всеми процессами в коде невозможно, да и нет необходимости. Использование сторонних компонентов и библиотек только усложняет дело. Именно поэтому программисты Delphi порой и сталкиваются со «своенравными» программами, которые то и дело норовят «сбросить пользователя». Итак, давайте рассмотрим некоторые вопросы, связанные с корректной средой программирования, так и непосредственно проблемы написания кода, которые ведут к возникновению ошибок типа «ошибка доступа» (AVS) и очертим наиболее известные пути их исправления.

Мы можем поделить AVS, с которыми сталкиваются при разработке в Delphi, на два основных типах: ошибки при выполнения и некорректная разработка проекта, что вызывает ошибки при работе программы.

Ошибки возникают при старте и закрытии Delphi или формировании проекта. Причиной могут являться сбои в «железе» компьютера.

Эти ошибки могут быть вызваны различными источниками, включая систему BIOS, операционную систему или аппаратные подпрограммы драйверов. Некоторые видео-, звуковые или сетевые платы могут фактически вызывать подобного рода ошибки в Delphi. Для решения подобных аппаратных проблем можно предпринять последовательность неких «стандартных» ходов:

  • проверить, что не имеется никаких конфликтов между установленными устройствами, устранить обнаруженные конфликты;
  • попробовать слегка уменьшить «аппетиты» видеодрайвера — поставить меньшее разрешение;
  • в случае если у вас двухпроцесорная система обеспечить равное изменение шага для каждого процессора;

И в конце концов просто попытаться заменить драйвера на более свежие.

Но помимо чисто железных проблем — большую головную боль могут вызвать ошибки в работе программного обеспечения. Особенно это касается непосредственно операционной системы. Зачастую Windows терпит крах спонтанно. Вот рекомендации которые помогут вам создать более устойчивую среду программирования:

Хотя Windows 9X популярная система, разработку лучше проводить в Windows NT или Windows 2000 — это более устойчивые операционные системы. Естественно, при переходе на них придется отказаться от некоторых благ семейства Windows 95/98/Me — в частности, не все программы адаптированы для Windows NT/2000. Зато вы получите более надежную и стабильную систему.

Не забывайте о том, как важно всегда иметь под рукой свежие версии компонентов для Delphi и дополнительных библиотек. В отличие от Windows создатели данных пакетов стараются от версии к версии уменьшать количество ошибок.

Следите за тем, чтобы устанавливаемые компоненты были предназначены непосредственно для вашей версии Delphi. Попробуйте деинсталлировать чужеродные компоненты один за другим (или пакет за пакетом), пока проблема не будет устранена.

Контролируйте все программные продукты, установленные на вашей машине и деинсталлируйте те из них, которые сбоят. Фаворитами AV среди них являются шароварные утилиты и программы и бета версии программных продуктов.

Все вышеперечисленное в основном не касалось самого процесса программирования и в малой степени зависит от разработчика. Теперь же обратимся к теме, как не допустить при разработке программного продукта ситуации, при которой он сам будет являться причиной ошибки.

Вы могли бы рассмотреть компилирование вашего приложения с директивой {$D}, данная директива компилятора может создавать файлы карты (файлы с расширением map, которые можно найти в том же каталоге, что и файлы проекта), которые могут послужить большой справкой в локализации источника подобных ошибок. Для лучшего «контроля» за своим приложением компилируйте его с директивой {$D}. Таким образом, вы заставите Delphi генерировать информацию для отладки, которая может послужить подспорьем при выявление возникающих ошибок.

Следующая позиция в Project Options — Linker & Compiler позволяет вам, определить все для последующей отладки. Лучше всего, если помимо самого выполняемого кода будет доступна и отладочная информация — это поможет при поиске ошибок. Отладочная информация увеличивает размер файла и занимает дополнительную память при компилировании программ, но непосредственно на размер или быстродействие выполняемой программы не влияет. Включение опций отладочной информации и файла карты дают детальную информацию только если вы компилируете программу с директивой {$D+}.

Эта информация состоит из таблицы номеров строк для каждой процедуры, которая отображает адреса объектных кодов в номера строк исходного текста. Директива $D обычно используется совместно с другой директивой — $L, что позволяет или запрещает генерацию информации о локальных символах для отладки.

Таким образом вы без труда сможете найти точный адрес той подпрограммы, которая была ответственна за ошибку. Одна из наиболее общих причин ошибок выполнения — использование объекта, который еще не был создан. Если второй адрес при выдачи ошибки — FFFFFFF (или 0000000) Вы можете почти утверждать, что было обращение к объекту, который еще не был создан. Например, вызов метода формы, которая не была создана.

procedure TfrMain.OnCreate(Sender: TObject);
 var BadForm: TBadForm;
 begin
   BadForm.Refresh; // причина  ошибки
 end;

Попытаемся разобратся в этой ситуации. Предположим, что BadForm есть в списке «Available forms» в окне Project Options|Forms. В этом списке находятся формы, которые должны быть созданы и уничтожены вручную. В коде выше происходит вызов метода Refresh формы BadForm, что вызывает нарушение доступа, так как форма еще не была создана, т.е. для объекта формы не было выделено памяти.

Если вы установите «Stop on Delphi Exceptions» в Language Exceptions tab в окне Debugger Options, возможно возникновение сообщения об ошибке, которое покажет, что произошло ошибка типа EACCESSVIOLATION. EACCESSVIOLATION — класс исключение для недопустимых ошибок доступа к памяти. Вы будете видеть это сообщение при разработке вашего приложения, т.е. при работе приложения, которое было запущено из среды Delphi.

Следующее окно сообщения будет видеть пользователь — и программа будет закрыта при совершение недопустимой операции:

 Access violation at address 0043F193
 in module 'Project1.exe'
 Read of address 000000.

Первое шестнадцатиричное число (‘0043F193’) — адрес ошибки во время выполнения программы. Выберите опцию меню ‘Search|Find Error’, введите адрес, в котором произошла ошибка (‘0043F193’) в диалоге и нажмите OK. Теперь Delphi перетранслирует ваш проект и покажет вам строку исходного текста, где произошла ошибка во время выполнения программы, то есть BadForm.Refresh.

Естественно, что списка наиболее общих причин ошибок, вызывающих аварийное завершение работы программы, написанной в Delphi, в чистом виде нет. Есть несколько общих «узких мест» в коде и структуре программы, когда подобная ошибка может произойти. Перечислим наиболее распространенные.

Недопустимый параметр API

Если вы пытаетесь передать недопустимый параметр в процедуру Win API, может произойти ошибка. Необходимо отслеживать все нововведения в API при выходе новых версий операционных систем и их обновлений.

Уничтожение исключения

Никогда не уничтожайте временный объект исключения. Обработка исключения автоматически уничтожает объект исключения. Если вы уничтожите объект самостоятельно, то приложение попытается уничтожать объект снова, и произойдет ошибка.

 Zero:=0;
 try
    dummy:= 10 / Zero;
 except on E: EZeroDivide do
    MessageDlg('Can not divide by zero!', mtError, [mbOK], 0);
    E.free. // причина ошибки
 end;

Индексация пустой строки

Пустая строка не имеет никаких достоверных данных. Следовательно, попытка индексировать пустую строку — подобно попытке обратиться к нулю, что приведет также к ошибке:

 var s: string;
 begin
    s:='';
    s[1]:='a'; // причина ошибки
 end;

Обращение к динамической переменной

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

procedure TForm1.Button1Click(Sender: TObject);
 var
   p1 : pointer;
   p2 : pointer;
 begin
   GetMem(p1, 128);
   GetMem(p2, 128);
  {эта строка может быть причиной ошибки}
   Move(p1, p2, 128);
  {данная строка корректна }
   Move(p1^, p2^, 128);
   FreeMem(p1, 128);
   FreeMem(p2, 128);
 end;

Перечисленные подходы позволят избежать наиболее частых недочетов в разработке, которые могут вызвать столь неприятное как для пользователя, так и для разработчика сообщение о том, что программа выполнила «недопустимую операцию».

Удачной вам ловли багов, господа!

Понравилась статья? Поделить с друзьями:
  • Application error 1208
  • Application error 1005 windows 10 как исправить
  • Application error 1000 windows 10 что это
  • Application error 1000 svchost
  • Application error 1000 shell32 dll