Блог GunSmoker-а

Содержание

Блог GunSmoker-а

. when altering one’s mind becomes as easy as programming a computer, what does it mean to be human.

19 апреля 2009 г.

Настройки проектов в Delphi с точки зрения поиска ошибок

О чём идёт речь

Сначала, давайте посмотрим на них: открываем Project/Options. Нас будут интересовать вкладки Compiling и Linking (в старых версиях Delphi они назывались Compiler и Linker):

Вкладка Compiling

Вкладка Linking

Напомним, что при смене любой из опций необходимо сделать полный Build проекту (а не просто Compile).

Что означают эти опции?

Самыми важными настройками являются группа опций «Debug information», «Local Symbols» и «Symbol reference info».

Программа представляет собой набор машинных команд. Текст программы представляет собой текстовый файл. Вопрос: как отладчик узнаёт, когда надо остановиться, если вы поставили бряк на строку в тексте? Где же соответствие между текстовым файлом и набором байт в exe-файле? Вот для такой связи и служит отладочная информация. Это, грубо говоря, набор инструкций типа: «машинные коды с 1056 по 1059 относятся к строке 234 модуля Unit1.pas». Вот с помощью такой информации и работает отладчик. Указанные выше опции отвечают за генерацию отладочной информации для ваших модулей.

Бывают ситуации, когда наличие отладочной информации в файле или (хотя бы) рядом с файлом является необходимым. Например, если вы выполняете удалённую отладку или отладку внешнего процесса. Или если вам нужен читаемый стек вызовов в вашем средстве диагностики исключений.

Подключение отладочной информации к приложению осуществляется несколькими способами: либо это опции проекта (а именно: «Map File», «Debug information» (Linker)/«Include TD32 Debug info» или «Include remote debug symbols»), либо это возможности всевозможных экспертов (типа EurekaLog, JCL или madExcept), которые добавляют отладочную информацию в программу в своём формате.

Хочу заметить, что помимо опций Delphi, в самих экспертах/инструментах также могут быть настройки, влияющие на детальность отладочной информации. Например, обзор таких настроек для EurekaLog мы уже делали в этой статье.

Обычное приложение без механизма диагностики исключений

Общие настройки для любых профилей

«Stack Frames» вообще включать незачем.

Генерацию map-файла выключаем.

Профиль Debug

Включаем «Range checking» и (по вкусу) «Overflow checking».

Профиль Release

Выключаем «Range checking», «Overflow checking», «Include TD32 debug info» и «Include remote debug info».

Приложение с механизмом диагностики исключений (типа EurekaLog, JCL или madExcept)

Общие настройки любых профилей

Все опции отладки («Debug information» (Compiler), «Local symbols», «Reference info») держать включёнными, т. к. в противном случае не будет доступна отладочная информация. Соответственно, ваши информационные механизмы пойдут лесом.

Генерацию map-файла включаем, если об этом не позаботился эксперт (маловероятно).

Профиль Debug

Профиль Release

Включаем «Use Debug DCUs».

Выключаем «Range checking», «Overflow checking», «Include TD32 debug info» и «Include remote debug info».

Примечание: если вы используете мало операций с индексами в своей программе (так что дополнительные проверки не замедлят её), то будет хорошей идеей всегда держать опцию «Range checking» включённой.

Debugging tips from Delphi 2009 Live!

Что может пойти не так, если настройки будут заданы неверно?

Ну, во-первых, это невозможность отладки (например, отсутствие информации для удалённого отладчика или выключенная опция «Debug information» (Compiler)), большой размер приложения (например, случайно забыли выключить «Debug information» (Linker)/«Include TD32 debug info»), медленная работа (например, компиляция с отладочным кодом), отсутствие или неполный стек вызовов в средствах диагностики исключений (например, выключили «Debug information» (Compiler)). В очень редких и запущенных случаях переключение опций может сказаться на работоспособности программы (например, установка Stack frames может снизить максимально возможную глубину рекурсии). Ну и недочёты по мелочи.

(**) Например: Button1Click состоит всего из двух инструкций: «call A; ret;». Она очень короткая и не использует аргументы или локальные переменные. Поэтому, очевидно, что ей не нужен стековый фрейм. Когда опция «Stack frames» выключена, то для Button1Click стековый фрейм не создаётся (но он создаётся, если опция «Stack frames» будет включена).

Но, для более сложных процедур стековые фреймы будут генерироваться вне зависимости от установки опции «Stack frames».

Например, тоже очень короткая процедура B всегда имеет фрейм. Причина: использование типа String в ShowMessage. Компилятору нужно вставить неявную строковую переменную и неявный try/finally для её освобождения, поэтому процедуре нужен фрейм.

В реальных приложениях фреймы генерируются для 99% процедур. Подробнее: Фреймы на стеке.

GetLastError — Функция Delphi

Что такое правильное использование GetLastError и FormatMessage в Delphi?

У меня есть проблема с использованием сторонних компонентов в Delphi 2006 (также Delphi 7), в котором я получаю «Неизвестная ошибка» при выполнении вызова функции к этому компоненту. У вас есть пример кода, который использует GetLastError и FormatMessage в Delphi, что позволит мне получить больше информации об ошибке? ТИА :)

Например, вы можете использовать эту функцию, чтобы отобразить последнюю ошибку:

Если вы хотите поднять исключение с этим сообщением, это еще проще:

В то время как DR правильно, есть проблема с этим подходом: Это не позволяет определить контекст, в котором произошла ошибка. Когда-нибудь видели ошибку «Функция API не удалось.» Whithout быть любой мудрее, какую функцию она была и где она happended?

Вот почему я написал функцию RaiseLastOsErrorEx и Win32CheckEx:

Эрудиты

Получить текст сообщения об ошибке Windows код которой получен функцией GetLastError?

. Данная функция описана в юните
( unit ) Windows и возвращает код последней ошибки, которая возникла в
Windows. Для того что бы не гадать, что именно произошло по коду, его
надо конвертировать в удобочитаемое текстовое

, которая описана в юните ( unit ) SysUtils и возвращает по коду ошибки
ее текст. Получить сообщение об ошибке можно при помощи следующего кода.

Напомню, что функция ShowMessage описана в юните ( unit ) Dialogs.

Еще интересные записи по данной теме

This entry was posted on Среда, Май 26th, 2010 at 14:52 and is filed under Delphi. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

GetLastError function

Retrieves the calling thread’s last-error code value. The last-error code is maintained on a per-thread basis. Multiple threads do not overwrite each other’s last-error code.

Visual Basic:В В Applications should call err. LastDllError instead of GetLastError.

Syntax

Parameters

This function has no parameters.

Return Value

The return value is the calling thread’s last-error code.

The Return Value section of the documentation for each function that sets the last-error code notes the conditions under which the function sets the last-error code. Most functions that set the thread’s last-error code set it when they fail. However, some functions also set the last-error code when they succeed. If the function is not documented to set the last-error code, the value returned by this function is simply the most recent last-error code to have been set; some functions set the last-error code to 0 on success and others do not.

Remarks

Functions executed by the calling thread set this value by calling the SetLastError function. You should call the GetLastError function immediately when a function’s return value indicates that such a call will return useful data. That is because some functions call SetLastError with a zero when they succeed, wiping out the error code set by the most recently failed function.

To obtain an error string for system error codes, use the FormatMessage function. For a complete list of error codes provided by the operating system, see System Error Codes.

The error codes returned by a function are not part of the Windows API specification and can vary by operating system or device driver. For this reason, we cannot provide the complete list of error codes that can be returned by each function. There are also many functions whose documentation does not include even a partial list of error codes that can be returned.

Error codes are 32-bit values (bit 31 is the most significant bit). Bit 29 is reserved for application-defined error codes; no system error code has this bit set. If you are defining an error code for your application, set this bit to one. That indicates that the error code has been defined by an application, and ensures that your error code does not conflict with any error codes defined by the system.

To convert a system error into an HRESULT value, use the HRESULT_FROM_WIN32 macro.

Как получить описание кода, полученного GetLastError?

Как получить описание кода, полученного GetLastError?

Функция RTL SysErrorMessage(GetLastError).

procedure TForm1.Button1Click(Sender: TObject);

Добавить комментарий

Не использовать не нормативную лексику.

Просьба писать ваши замечания, наблюдения и все остальное,
что поможет улучшить предоставляемую информацию на этом сайте.

ВСЕ КОММЕНТАРИИ МОДЕРИРУЮТСЯ ВРУЧНУЮ, ТАК ЧТО СПАМИТЬ БЕСПОЛЕЗНО!

GetLastError Routine

Unit Edit

Description Edit

It will return the value of the last failed windows API call reported by the OS. Normally after calling this function the error state of the OS will be reset.

GetLastError function is a wrapper function for GetLastError.

Technical Comments Edit

(Known issues / Documentation clarifications / Things to be aware of)

Examples Edit

(Please provide links to articles/source code that show how to use this item.)

See Also Edit

(Please provide links to items specifically related to this item.)

User Comments/Tips Edit

(Please leave your name with your comment.)

Почему GetLastError возвращает 0, когда он вызывается в библиотеке DLL?

Предположим, у меня есть библиотека DLL с этим псевдокодом:

Почему GetLastError функция возвращает 0, когда она используется в библиотеке DLL, как показано выше? Есть ли способ получить последний код ошибки для этого случая?

2 ответа

Ваш звонок GetLastError возвращает 0 потому что есть другие API, вызываемые после того, как CreateFile и ваш код исключения выполняется.

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

документация объясняет это следующим образом:

На более высоком уровне реальная проблема с этим кодом заключается в том, что он смешивает модели. Вы пытаетесь создать или открыть файл с одной системой (система VCL TStream), но вы проверяете ошибки, вызванные другой системой (Win32 API).

Единственный способ, которым вы можете положиться на результат Win32 GetLastError, — это если вы сами вызываете функции Win32. Зачем? Потому что это единственный способ убедиться, что между вызовом функции Win32 и вашим вызовом GetLastError нет других вызовов функций Win32. Каждый вызов Win32 API может (пере) установить GetLastError.

Несмотря на то, что VCL находится поверх Win32, существует много возможностей для некоторых других вызовов Win32 API между тем, когда возникает ошибка и когда исключение достигает вашего обработчика. Даже если сегодня все работает хорошо, некоторые будущие изменения в реализации VCL могут легко нарушить счастливое совпадение текущей ситуации.

Лучший способ избежать этого «времени зависания», когда необходимые данные уязвимы для перезаписи, — это получить значение GetLastError как можно ближе к точке сбоя и включить его в свойство объекта исключения VCL. Это практически исключает риск невинного нарушения вашего обработчика исключений и точки сбоя, уничтожающей глобальное состояние GetLastError.

GetLastError — Функция Delphi

uses
Windows, SysUtils;

function GetCursor: Integer;
asm
MOV DX, 3D4h
MOV AL, 0Fh
OUT DX, AL
INC DX
XOR EAX, EAX
IN AL, DX
end;

var
H: THandle;
E: Cardinal;
Msg: PAnsiChar;

begin
H := CreateFile(‘\\\\.\\GIVEIO’, GENERIC_READ, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
E := GetLastError;
if H = INVALID_HANDLE_VALUE then
begin
if FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_ALLOCATE_BUFFER, nil, 0,
LANG_RUSSIAN, Msg, 0, nil) <> 0 then
Writeln (‘ERROR_RESOURCE_LANG_NOT_FOUND’);
Writeln (‘Couldn»t access giveio device’);
Writeln (‘Error ‘, E, ‘: ‘, Msg);
Readln;
Halt;
end;
CloseHandle(H);
Writeln(GetCursor);
Readln;
end.

во-вторых нужно передавать не Msg, а @Msg.

в-третьих функция FormatMessage возвращает количество символов в описании ошибки

А вообще коды ошибок описаны в MSDN и лазить по winnt. h вовсе не к чему.

GetLastError function

Retrieves the calling thread’s last-error code value. The last-error code is maintained on a per-thread basis. Multiple threads do not overwrite each other’s last-error code.

Visual Basic:В В Applications should call err. LastDllError instead of GetLastError.

Syntax

Parameters

This function has no parameters.

Return Value

The return value is the calling thread’s last-error code.

The Return Value section of the documentation for each function that sets the last-error code notes the conditions under which the function sets the last-error code. Most functions that set the thread’s last-error code set it when they fail. However, some functions also set the last-error code when they succeed. If the function is not documented to set the last-error code, the value returned by this function is simply the most recent last-error code to have been set; some functions set the last-error code to 0 on success and others do not.

Remarks

Functions executed by the calling thread set this value by calling the SetLastError function. You should call the GetLastError function immediately when a function’s return value indicates that such a call will return useful data. That is because some functions call SetLastError with a zero when they succeed, wiping out the error code set by the most recently failed function.

To obtain an error string for system error codes, use the FormatMessage function. For a complete list of error codes provided by the operating system, see System Error Codes.

The error codes returned by a function are not part of the Windows API specification and can vary by operating system or device driver. For this reason, we cannot provide the complete list of error codes that can be returned by each function. There are also many functions whose documentation does not include even a partial list of error codes that can be returned.

Error codes are 32-bit values (bit 31 is the most significant bit). Bit 29 is reserved for application-defined error codes; no system error code has this bit set. If you are defining an error code for your application, set this bit to one. That indicates that the error code has been defined by an application, and ensures that your error code does not conflict with any error codes defined by the system.

To convert a system error into an HRESULT value, use the HRESULT_FROM_WIN32 macro.

ASD-SOFT

Программирование. Теория и практика.

WinInet в Delphi. Начало. HTTP запрос.

Здравствуйте уважаемые коллеги!

Библиотека WinInet, или Win32 Internet Extensions, предоставляет набор API функций для работы с протоколами HTTP и FTP. В данном примере я покажу как используя данную библиотеку получить исходный HTML код страницы.

Для работы с API нам понадобиться добавить в раздел USES модуль Winapi. WinInet (или просто WinInet для более поздних версий Delphi).

Для начала опишу функции WinInet, которые понадобятся мне в данном примере:

InternetOpen

Это первая функция WinINet, которая должна вызываться в приложении. Она говорит DLL инициализировать внутренние структуры данных и подготовиться к будущим вызовам приложения. В случае неудачи вернет NIL. Информацию об ошибке можно получить с помощь функции GetLastError.

lpszAgent — Указатель на строку содержащую имя приложения, которое используется как user agent в HTTP протоколе.
dwAccessType — Указывает какой тип доступа использовать из списка значений:

INTERNET_OPEN_TYPE_DIRECT Прямое подключение.
INTERNET_OPEN_TYPE_PRECONFIG Получить настройки подключения из реестра.
INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY Получает настройки из реестра и предотвращает использование Microsoft JScript или Internet Setup (INS) файла.
INTERNET_OPEN_TYPE_PROXY Доступ через прокси сервер.

lpszProxy — Указатель на строку содержащую адрес прокси сервера, если dwAccessType указан INTERNET_OPEN_TYPE_PROXY.
lpszProxyBypass — Указатель на строку, которая содержит адреса, которые не нужно передавать через прокси.
dwFlags — Флаг дополнительных опций, который может принимать значение:

INTERNET_FLAG_ASYNC Выполнять только асинхронные запросы.
INTERNET_FLAG_FROM_CACHE Все запросы возвращаются только из кэша. Если запрашиваемого элемента нет в кэше, то возвращается ошибка ERROR_FILE_NOT_FOUND.
INTERNET_FLAG_OFFLINE Аналогично INTERNET_FLAG_FROM_CACHE запросы возвращаются из кэша.

InternetConnect

Функция открывает сессию работы с FTP или HTTP протоколом для указанного сайта. При неудаче возвращает NIL.

hInet — Указатель созданный функцией InternetOpen.
lpszServerName — Указатель на строку содержащую имя сервера, например asd-soft. ru или IP адрес.
nServerPort — Порт сервера. Можно использовать константы:

INTERNET_DEFAULT_FTP_PORT Порт FTP по умолчанию (21).
INTERNET_DEFAULT_HTTP_PORT Порт HTTP по умолчанию (80).
INTERNET_DEFAULT_HTTPS_PORT Порт HTTPS по умолчанию (443).
INTERNET_DEFAULT_SOCKS_PORT Порт SOCKS по умолчанию (1080).
INTERNET_INVALID_PORT_NUMBER Использовать стандартный порт для службы, указанной в dwService.

lpszUsername — Указатель на строку, которая определяет имя пользователя. Если параметр NIL, то функция использует значение по умолчанию. Для FTP протокола это «anonymous».
lpszPassword — Указатель на строку, которая определяет пароль пользователя.
dwService — Определяет тип сервиса:

INTERNET_SERVICE_FTP FTP протокол.
INTERNET_SERVICE_GOPHER Gopher.
INTERNET_SERVICE_HTTP HTTP протокол.

dwFlags — Опции, специфичные для выбранного сервиса в dwService.
dwContext — Указатель на функцию, которая будет обрабатывать возвращаемые события. Например, при асинхронной работе.

HttpOpenRequest

Подготовка HTTP запроса.

hConnect — Указатель на HTTP сессию, созданную функцией InternetConnect.
lpszVerb — Указатель на строку с типом запроса GET или POST. Если указать NIL, то будет использоваться GET запрос.
lpszObjectName — Указатель на строку, которая содержит объект запроса. Это может быть HTML страница, скрипт или файл.
lpszVersion — Указатель на строку с версией протокола. Если передать NIL, то функция использует HTTP версии 1.1 или 1.0 в зависимости от настроек Internet Explorer.
lpszReferrer — Указатель на строку с адресом предыдущей страницы.
lplpszAcceptTypes — Указатель на строку с типом содержимого. Какие именно значения могут быть переданы описаны в этом документе.
dwFlags — Набор флагов из списка:

INTERNET_FLAG_CACHE_IF_NET_FAIL Возвращать данные из кэша, если сеть не доступна.
INTERNET_FLAG_HYPERLINK Перезагружает данные из сети, если нет Expires time или LastModified time.
INTERNET_FLAG_IGNORE_CERT_CN_INVALID Отключает проверку SSL/PCT сертификатов, которые возвращает сервер.
INTERNET_FLAG_IGNORE_CERT_DATE_INVALID Отключает проверку SSL/PCT сертификатов на достоверные даты.
INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP При использовании этого флага WinInet позволяет делать переадресацию с HTTPS на HTTP адреса.
INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS При использовании этого флага WinInet позволяет делать переадресацию с HTTP на HTTPS адреса.
INTERNET_FLAG_KEEP_CONNECTION Поддерживать соединение с сервером.
INTERNET_FLAG_NEED_FILE Указывается в случае, если временный файл должен быть создан при отсутствии в кэше.
INTERNET_FLAG_NO_AUTH Не использовать автоматическую аутентификацию.
INTERNET_FLAG_NO_AUTO_REDIRECT Не использовать автоматическую переадресацию.
INTERNET_FLAG_NO_CACHE_WRITE Не добавляет данные в кэш.
INTERNET_FLAG_NO_COOKIES Отключает использование кукисов.
INTERNET_FLAG_NO_UI Отключает диалоговое окно cookie.
INTERNET_FLAG_PRAGMA_NOCACHE Получать данные с исходного сервера, даже при наличии их в кэше прокси сервера.
INTERNET_FLAG_RELOAD Запрашивает загрузку данных с сервера, а не из кэша.
INTERNET_FLAG_RESYNCHRONIZE Перезагрузить HTTP ресурсы, если они были изменены с момента последней загрузки.
INTERNET_FLAG_SECURE Использовать безопасные SSL/PCT транзакции. Имеет смысл только для HTTP запросов.

dwContext — Ссылка на ресурсы связанные с этим запросом.

HttpSendRequest

Отправляет HTTP запрос. Возвращает True в случае удачного выполнения запроса.

hRequest — Указатель на запрос подготовленный функцией HttpOpenRequest.
lpszHeaders — Указатель на строку с дополнительными заголовками запроса.
dwHeadersLength — Длинна дополнительных заголовков.
lpOptional — Указатель на буфер, содержащий дополнительные данные. Этот параметр обычно используется при POST и PUT запросах.
dwOptionalLength — Размер передаваемого буфера.

HttpQueryInfo

Запросить информацию связанную с HTTP запросом.

hRequest — Указатель на запрос подготовленный функцией HttpOpenRequest.
dwInfoLevel — Набор флагов, определяющих тип возвращаемой информации. Со списком возможных флагов можно ознакомиться на данной странице. В нашем примере нам понадобится всего два:

HTTP_QUERY_FLAG_NUMBER Указывает на то, что нужно возвращать число в качестве статуса.
HTTP_QUERY_STATUS_CODE Нужно возвращать стату. Список возможных статусов перечислен на этой странице.

lpvBuffer — Указатель на буфер для возвращаемой информации. Этот параметр не может быть NIL.
lpdwBufferLength — Указатель на переменную, в которую будет записан размер возвращаемого буфера.
lpdwReserved — Указатель на переменную в которой содержится индекс заголовка возвращаемой информации.

InternetQueryDataAvailable

Запрашивает кол-во данных полученных в результате запроса.

hFile — Указатель на запрос подготовленный функцией HttpOpenRequest.
lpdwNumberOfBytesAvailable — Указатель на переменную в которую будет передано кол-во доступных байт.
dwFlags — Параметр не используется и должен быть равным 0.
dwContext — Параметр не используется и должен быть равным 0.

InternetReadFile

Читает данные полученные запросом.

hFile — Указатель на запрос подготовленный функцией HttpOpenRequest.
lpBuffer — Указатель на буфер для чтения данных.
dwNumberOfBytesToRead — Кол-во байт для чтения.
lpdwNumberOfBytesRead — Кол-во прочитанных байт.

InternetCloseHandle

Освобождает указатель созданный функциями InternetOpen, InternetConnect или HttpOpenRequest.

hInet — Указатель.

И последняя функция, которая не относится к API WinInet, но которая нам понадобиться: GetLastError — Возвращает код последней ошибки.

Теперь напишем код, который получит HTML код страницы с адресом https://asd-soft. ru/delphi-wininet-begin-http

Результатом выполнения данного кода будет HTML код страницы в переменной ResponseString.

Функция SysErrorMessage — возвращает текст ошибки по коду из GetLastError.

У кого нибудь есть таблица описания кода ошибкок в Delphi (C++ Builder)?

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

Большинство функций, которые устанавливают последнее значение кода ошибки потока, устанавливает его тогда, когда они завершаются ошибкой; несколько функций устанавливают код ошибки, когда они завершаются успешно. Функция, которая завершилась сбоем, обычно указывается кодом ошибки величины возвращаемого значения типа нуля, ПУСТО (NULL) или — (минус) 1. Некоторые функции вызывают SetLastError при условии успешного завершения; на такие случаи обращается внимание в статьях справочника для каждой функции.

Источники:

https://www. gunsmoker. ru/2009/04/delphi_19.html

https://studiowb. ru/getlasterror-funkcija-delphi/

Понравилась статья? Поделиться с друзьями:
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: