Чтение онлайн

на главную - закладки

Жанры

О чём не пишут в книгах по Delphi

Григорьев Антон Борисович

Шрифт:

function SafeLoadLibrary(const Filename: string; ErrorMode: UINT): HMODULE;

var

 OldMode: UINT;

 FPUControlWord: Word;

begin

 OldMode := SetErrorMode(ErrorMode);
 

 try

asm

FNSTCW FPUControlWord

end;

try

Result := LoadLibrary(PChar(Filename));

finally

asm

FNCLEX

FLDCW FPUControlWord

end;

end;

 finally

SetErrorMode(OldMode);

 end;

end;

Как

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

В функции

CreateADOObject
(внутренняя функция модуля
ADODB
) тоже сохраняется и восстанавливается управляющее слово (листинг 3.14).

Листинг 3.14. Функция
CreateADOObject
модуля
ADODB

function CreateADOObject(const ClassID: TGUID): IUnknown;

var

 Status: HResult;

 FPUControlWord: Word;

begin

 asm

FNSTCW FPUControlWord

 end;

 Status :=

CoCreateInstance(ClassID, nil, CLSTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER, IUnknown, Result);

 asm

FNCLEX

FLDCW FPUControlWord

 end;

 if (Status = REGDB_E_CLASSNOTREG) then

raise Exception.CreateRes(@SADOCreateError)

 else OleCheck(Status);

end;

Здесь восстанавливать управляющее слово приходится после вызова системной функции

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

Аналогичную защиту можно обнаружить в модуле

Dialogs
, в методе
TCommonDialog.TaskModalDialog
. Комментарий к этой защите гласит: "Avoid FPU control word change in NETRAP.dll, NETAPI32.dll, etc".

В модуле

Windows
особым образом импортируются функции
CreateWindow
и
CreateWindowEx
, которые, видимо, тоже были замечены в некорректном обращении с управляющим словом FPU. Вот как, например, выглядит импорт функции
CreateWindowEx
(листинг 3.15).

Листинг 3.15. Импорт функции
CreateWindowEx
модулем
Windows

function _CreateWindowEx(dwExStyle: WORD; lpClassName: PChar; lpWindowName: PChar; dwStyle: DWORD; X, Y, nWidth, nHeight: Integer; hWndParent: HWND; hMenu: HMENU; hInstance: HINST; lpParam: Pointer): HWND; stdcall; external user32 name 'CreateWindowExA';

function CreateWindowEx(dwExStyle: DWORD; lpClassName: PChar; lpWindowName: PChar; dwStyle: DWORD; X, Y, nWidth, nHeight: Integer; hWndParent: HWND; hMenu: HMENU; hInstance: HINST; lpParam: Pointer): HWND;

var

 FPUCW: Word;

begin

 FPUCW := Get8087CW;

 Result :=

_CreateWindowEx(dwExStyle, lpClassName, lpWindowName,

dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu,

hInstance, lpParam);

 Set8087CW(FPUCW);

end;

Модуль

Windows
импортирует функцию
CreateWindowExA
из библиотеки user32.dll, но дает ей измененное название и не показывает ее в своем интерфейсе. Вместо этого он экспортирует другую функцию с названием
CreateWindowEx
(и аналогичную с названием
CreateWindowExA
), которая является оберткой над настоящей
CreateWindowExA
и обеспечивает сохранение значения управляющего слова FPU. Аналогичным способом импортируется и Unicode-вариант функции. Таким образом, стандартные библиотеки обеспечивают вызов безопасного варианта
CreateWindowEx
в любой программе.

Примечание

В модуле

Windows
можно обнаружить еще одну интересную деталь: функции
CreateWindowA
и
CreateWindowW
из библиотеки user32.dll этим модулем вообще не импортируются. Вместо этого одноименные обертки вызывают импортированные функции
_CreateWindowExA
и
_CreateWindowExW
, передавая им 0 в качестве значения параметра
dwExStyle
.

3.2.12. Машинное эпсилон

Когда мы имеем дело с вычислениями с ограниченной точностью, возникает такой парадокс. Пусть, например, мы считаем с точностью до трех значащих цифр. Прибавим к числу 1,00 число 1,00·10– 4. Если бы все было честно, мы получили бы 1,0001. Но у нас ограничена точность, поэтому мы вынуждены округлять до трех значащих цифр. В результате получается 1,00. Другими словами, к некоторому числу мы прибавляем другое число, большее нуля, а в результате из-за ограниченной точности мы получаем то же самое число. Наименьшее положительное число, которое при добавлении его к единице дает результат, не равный единице, называется машинным эпсилон.

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

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

Extended
содержит 64 разряда. Чтобы закодировать единицу, старший бит мантиссы должен быть равен 1 (денормализованная запись), остальные биты — нулю. Очевидно, что при такой записи наименьшее из чисел, для которых выполняется условие x > 1, получается, когда самый младший бит мантиссы тоже будет равен единице, т.е. х = 1,00...001 (в двоичном представлении, между точкой и младшей единицей 62 нуля). Таким образом, машинное эпсилон равно х– 1, т.е. 0.00...001. В более привычной десятичной форме записи это будет 2– 63, т.е. примерно 1,084·10– 19.

Поделиться:
Популярные книги

Безымянный раб [Другая редакция]

Зыков Виталий Валерьевич
1. Дорога домой
Фантастика:
боевая фантастика
9.41
рейтинг книги
Безымянный раб [Другая редакция]

Измена. Свадьба дракона

Белова Екатерина
Любовные романы:
любовно-фантастические романы
эро литература
5.00
рейтинг книги
Измена. Свадьба дракона

Не грози Дубровскому! Том VIII

Панарин Антон
8. РОС: Не грози Дубровскому!
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Не грози Дубровскому! Том VIII

Последняя Арена 7

Греков Сергей
7. Последняя Арена
Фантастика:
рпг
постапокалипсис
5.00
рейтинг книги
Последняя Арена 7

На границе империй. Том 9. Часть 3

INDIGO
16. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 3

Все не так, как кажется

Юнина Наталья
Любовные романы:
современные любовные романы
7.70
рейтинг книги
Все не так, как кажется

Я же бать, или Как найти мать

Юнина Наталья
Любовные романы:
современные любовные романы
6.44
рейтинг книги
Я же бать, или Как найти мать

Боярышня Дуняша

Меллер Юлия Викторовна
1. Боярышня
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Боярышня Дуняша

Аромат невинности

Вудворт Франциска
Любовные романы:
любовно-фантастические романы
эро литература
9.23
рейтинг книги
Аромат невинности

Кодекс Крови. Книга IХ

Борзых М.
9. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга IХ

Свет во мраке

Михайлов Дем Алексеевич
8. Изгой
Фантастика:
фэнтези
7.30
рейтинг книги
Свет во мраке

Приручитель женщин-монстров. Том 3

Дорничев Дмитрий
3. Покемоны? Какие покемоны?
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Приручитель женщин-монстров. Том 3

Жестокая свадьба

Тоцка Тала
Любовные романы:
современные любовные романы
4.87
рейтинг книги
Жестокая свадьба

Безродный

Коган Мстислав Константинович
1. Игра не для слабых
Фантастика:
боевая фантастика
альтернативная история
6.67
рейтинг книги
Безродный