Подтвердить что ты не робот

Отладка ошибок при нарушении доступа?

Какие советы вы можете поделиться, чтобы помочь найти и устранить нарушения прав при написании приложений в Delphi?

Я считаю, что нарушения доступа обычно вызваны попыткой доступа к тому, что еще не было создано в памяти, например Object и т.д.

Мне сложно определить, что вызывает нарушения доступа, а затем, где нужно сделать необходимые изменения, чтобы попытаться остановить/исправить их.

Пример - это личный проект, над которым я сейчас работаю. Я храню в TTreeView Node. Свойство данных содержит некоторые данные для каждого Node. Узлы могут быть выбраны и экспортированы несколькими экземплярами (экспорт повторяется через каждый выбранный node и сохраняет определенные данные в текстовом файле - информация, сохраненная в текстовом файле, - это то, что хранится в node.data). Файлы также можно импортировать в Treeview (сохранение содержимого текстовых файлов в Node.data).

Проблема в этом примере заключается в том, что я импортирую файлы в Treeview, а затем экспортирую их, он работает отлично. Однако, если я добавлю node во время выполнения и экспортирую их, я получаю:

"Нарушение доступа по адресу 00405772 в модуле Project1.exe. Чтение адреса 00000388."

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

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

Поэтому советы и советы будут очень полезны.

4b9b3361

Ответ 1

Это означает, что ваш код обращается к той части памяти, которой она не разрешена. Это обычно означает, что у вас есть указатель или объект, указывающий на неправильную память. Может быть, потому, что он не инициализирован или уже выпущен.

Используйте отладчик, например, Delphi. Он расскажет вам, в какой строке кода произошел AV. Оттуда выясните свою проблему, посмотрев на столбец и локальные переменные и т.д. Иногда это также помогает, если вы компилируете с DCU Debug.

Если у вас нет отладчика, потому что это происходит только на стороне клиента, вы можете использовать MadExcept или JclDebug для регистрации исключения с помощью callstack и отправить его вам. Это дает вам меньше деталей, но может указывать на вас в правильном направлении.

Есть некоторые инструменты, которые могли бы найти такие проблемы раньше, проверяя более агрессивно. У диспетчера памяти FastMM есть такие параметры.

ИЗМЕНИТЬ

"Нарушение доступа по адресу 00405772 в модуле Project1.exe. Читайте адрес 00000388."

Таким образом, ваша проблема приводит к AV-адресу по адресам 00405772 в модуле Project1.exe. Отладчик Delphi выведет вас в нужную строку кода (или используйте "Найти ошибку" ).

Он пытается прочитать память по адресу 00000388. Это довольно близко к 00000000 (ноль), поэтому это, вероятно, означает доступ к некоторому указателю/ссылке на массив или динамический массив, который равен нулю. Если бы это был массив байтов, это был бы элемент 388. Или это может быть поле довольно большого объекта или записи с большим количеством полей. Указатель/ссылка объекта или записи будет нулевым.

Ответ 2

Я нахожу, что действительно труднодоступные нарушения доступа не всегда возникают во время работы в отладчике. Хуже того, они случаются с клиентами, а не со мной. В принятом ответе упоминается об этом, но я действительно думаю, что это должно быть дано более подробно: MadExcept предоставляет трассировку стека, которая дает мне ценную контекстную информацию и помогает мне увидеть, где сбой кода, или имеет необработанные исключения (это не только для нарушений доступа). Это даже дает возможность клиентам отправлять вам сообщения об ошибках прямо из вашей программы. Это приводит к обнаружению и исправлению большего количества нарушений, о которых сообщают ваши бета-тестеры или ваши пользователи.

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

В-третьих, я нашел такие инструменты, как Pascal Analyzer от Peganza, а функция аудита и метрики в некоторых выпусках Delphi может помочь вам найти области вашего кода, которые имеют проблемы. В качестве одного конкретного примера, Pascal Analyzer нашел места, где я забыл сделать что-то важное, что приведет к сбою или нарушению доступа.

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

Ответ 3

Я хотел бы упомянуть еще один инструмент, который я использую, когда другие инструменты не могут обнаружить AV. Это SafeMM (более новая версия). Однажды он указал мне на небольшую 5-строчную процедуру. И мне пришлось смотреть на него более 10 минут, чтобы увидеть AV, который там был. Вероятно, в тот день мои навыки программирования не были максимальны, но вы знаете, что плохие вещи обычно происходят именно в такие дни.