Читаем О чём не пишут в книгах по Delphi полностью

Такой код компилируется и даже, за редким исключением, дает ожидаемый результат. Но тем не менее, в этом коде грубая ошибка. Указатель, возвращаемый функцией, указывает на область памяти, которая считается свободной, поскольку после выхода переменной S за пределы области видимости память, которую занимала эта строка, освободилась. Менеджер памяти может в любой момент вернуть эту память системе (тогда обращение к ней вызовет Access violation) или задействовать для других целей (тогда новая информация уничтожит содержащуюся там строку). Проблема маскируется тем, что обычно результат используется немедленно, до того как менеджер памяти что-то сделает с этим блоком. Тем не менее полагаться на это и писать такой код не следует.

<p>3.4. Прочие "подводные камни"</p>

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

<p>3.4.1. Порядок вычисления операндов</p>

Эта проблема связана с тем, что у человека есть определенные интуитивные представления о порядке выполнения действий программой, однако компилятор не всегда им соответствует. Рассмотрим следующий код (листинг 3.47, пример OpOrder на компакт-диске).

Листинг 3.47. "Неправильный" порядок вычисления операндов

var

 X: Integer;

function GetValueAndModifyX: Integer;

begin

 X:= 1;

 Result:= 2;

end;

procedure TForm1.Button1Click(Sender: TObject);

var

 A1, A2: Integer;

begin

 X:= 2;

 A1:= X + GetValueAndModifyX;

 X:= 2;

 А2:= GetValueAndModifyX + X;

 Label1.Caption:= IntToStr(A1);

 Label2.Caption:= IntToStr(A2);

end;

Суть этого примера заключается в том, что функция GetValueAndModifyX имеет побочный эффект — изменяет значение глобальной переменной X. И эту же переменную мы используем при вычислении выражения, в которое входит также вызов GetValueAndModifyX. При вычислении A1 в выражении сначала упоминается X, а потом GetValueAndModifyX, при вычислении А2 — наоборот. Логично было бы предположить, что A1 получит значение 4, А2 — 3, т. к. вычисление первого операнда должно выполняться раньше второго. В действительности же обе переменные получат значение 3, поскольку компилятор сам выбирает порядок вычисления операндов независимо от того, в каком порядке они упоминаются в выражении. То же самое касается любых коммутативных операций: умножения, арифметических and, or и xor. Посмотрим, что будет для некоммутативных операций, например, для деления (листинг 3.48).

Листинг 3.48. "Неправильный" порядок вычисления операндов при делении

procedure TForm1.Button2Click(Sender: TObject);

var

 A1, A2: Extended;

begin

 X:= 2;

 A1:= X / GetValueAndModifyX;

 X:= 2;

 A2:= GetValueAndModifyX / X;

 Label1.Caption:= FloatToStr(A1);

 Label2.Caption:= FloatToStr(A2);

end;

В результате выполнения этого кода A1 получает значение 0.5, A2 — 2, т. е. и здесь сначала вычисляется функция, а потом берется значение переменной X.

Если бы функция GetValueAndModifyX не имела побочных эффектов (т. е. только возвращала бы результат и больше ничего не меняла), порядок вычисления аргументов был бы нам безразличен. Вообще, функции, имеющие побочные эффекты, считаются потенциальным источником ошибок, поэтому их написание нежелательно. Но в некоторых случаях (например, в функции Random) обойтись без побочных эффектом невозможно.

Примечание

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

Ради интереса посмотрим, что будет, если вторым аргументом тоже будет функция, зависящая от X, (листинг 3.49).

Листинг 3.49. Сложение двух операндов с побочными эффектами

function GetX: Integer;

begin

 Result:= X;

end;

procedure TForm1.Button3Click(Sender: TObject);

var

 A1, A2: Integer;

begin

 X:= 2;

 A1:= GetX + GetValueAndModifyX;

 X:= 2;

 A2:= GetValueAndModifyX + GetX;

 Label1.Caption:= IntToStr(A1);

 Label2.Caption:= IntToStr(A2);

end;

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных