(495) 925-0049, ITShop интернет-магазин 229-0436, Учебный Центр 925-0049
  Главная страница Карта сайта Контакты
Поиск
Вход
Регистрация
Рассылки сайта
 
 
 
 
 

Нельзя, но можно в Delphi, или аномалии Delphi и почему это работает

Источник: RSDN Magazine #6-2004

Меня заинтересовал один момент в Delphi - почему, когда я забываю создать объект класса, программа вываливается, тем не менее, только внутри метода?

Я решил протестировать эту особенность в различных вариациях:

TForm1

type
  TSomeClass = class (TObject)
  private
    FProperty : Integer;
    function SomeFunc(pParam : Integer; var pSelf : TSomeClass) : Integer;
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  xObj : TSomeClass;
  x, y : Integer;
begin
  x := StrToInt(Edit1.Text);
  xObj.SomeFunc(x, xObj);
  y := xObj.FProperty;
  xObj.Free;
  Edit2.Text := IntToStr(y);
end;

function TSomeClass.SomeFunc(pParam : Integer; var pSelf : TSomeClass): Integer;
var
  i : Integer;
begin
  Self := TSomeClass.Create;
  pSelf := Self;
  Result := 0;
  for i := 1 to pParam do
    Result := Result + i;
  FProperty := Result;
end;

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

Обратите внимание на описание следующего класса:

TSomeClass

  TSomeClass = class (TObject)
  private
    FProperty : Integer;
    function SomeFunc(pParam : Integer; var pSelf : TSomeClass) : Integer;
  end;

И свойство, и метод его объявлены как private. Но, тем не менее, следующий код вполне замечательно компилируется:

TForm1.Button1Click

procedure TForm1.Button1Click(Sender: TObject);
var
  xObj : TSomeClass;
  x, y : Integer;
begin
  x := StrToInt(Edit1.Text);
  xObj.SomeFunc(x, xObj);
  y := xObj.FProperty;
  xObj.Free;
  Edit2.Text := IntToStr(y);
end;

Как видно, доступ к свойству и методу абсолютно свободен. Но это - широко известная аномалия защиты Delphi, заключающаяся в том, что код имеет доступ ко всем (даже приватным) данным и методам классов, описанных в том же модуле.

Далее - более интересный момент. Во второй строчке вызывается метод несуществующего объекта! Это уже хитрость, связанная с особенностью компиляции классов. Дело в том, что при компиляции класса в код все имеющиеся у него функции сразу компилируются в функции с неявным аргументом - ссылкой Self. Так вот, этот Self и есть ссылка на память, отведенную под член-данные объекта. И эта память выделяется при вызове функций, помеченных как constructor, и высвобождается при вызове функций, помеченных как destructor! Получается, что все методы в объекте - это почти методы классов (Class methods, в терминологии Delphi), за исключением параметра Self! Т. е. разница между ними только в синтаксисе вызова и в неявном параметре. Деструкторы отличаются от них тем, что неявно содержат код освобождения памяти. Соответственно, конструкторы не содержат Self как аргумент, но возвращают его после выделения памяти под данные объекта.

Теперь давайте сфокусируемся на методе класса:

TSomeClass.SomeFunc

function TSomeClass.SomeFunc(pParam : Integer; var pSelf : TSomeClass): Integer;
var
  i : Integer;
begin
  Self := TSomeClass.Create;
  pSelf := Self;
  Result := 0;
  for i := 1 to pParam do
    Result := Result + i;
  FProperty := Result;
end;

Он содержит одну локальную переменную, память под которую опять же выделяется при компиляции класса! Теперь мы создадим объект класса стандартным конструктором и присвоим Self ссылку на этот объект. Опять всё работает! Delphi позволяет модифицировать переменную Self! Именно это и позволяет написать последнюю строчку в этой функции, ведь теперь-то память под данные у нас выделена! Ссылку на эту область памяти мы и вернём через параметр pSelf.

Вернёмся опять к процедуре TForm1.Button1Click. Так как после вызова метода xObj.SomeFunc(x, xObj) переменная xObj содержит ссылку на выделенную область памяти, доступ к xObj.FProperty у нас уже есть - мы получили от операционной системы 4 байтика, требуемые для ее хранения. Поэтому y := xObj.FProperty работает тоже без проблем. Ну и, наконец, xObj.Free возвращает взятую нами память обратно операционной системе. После этого, несмотря на то, что там лежат вычисленные нами данные, доступа туда у нас уже нет (обращение к xObj.FProperty будет вызывать ошибку доступа к памяти Access Violation). Именно поэтому программа падает уже внутри методов, даже если память под объект не была выделена.

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

Ссылки по теме


 Распечатать »
 Правила публикации »
  Обсудить материал в конференции Micro Focus/Borland » [2]
Написать редактору 
 Рекомендовать » Дата публикации: 12.02.2007 
 

Магазин программного обеспечения   WWW.ITSHOP.RU
The BAT! Home- 1 компьютер
Symantec Ghost Solution Suite, License, 1-24 Devices
SAP Crystal Reports XI R2 Dev 2006 INTL WIN NUL License (Version 11)
ABBYY FineReader 14 Standard Full
Allround Automation Direct Oracle Access Standard license
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Новости ITShop.ru - ПО, книги, документация, курсы обучения
Программирование на Microsoft Access
CASE-технологии
Компьютерный дизайн - Все графические редакторы
СУБД Oracle "с нуля"
Delphi - проблемы и решения
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
Обсуждения в форумах
Ищу программиста PYTHON (1)
Ищу программиста для написание программ python 3 + библиотека tkinter Есть данные в БД...
 
Пишу программы на заказ профессионально (2265)
Пишу программы на заказ на языках Pascal (численные методы, списки, деревья, прерывания) под...
 
Ищу программиста для написания программы (17)
Ищу программиста ,владеющего Вижуал Бэйсик и программированием в Экселе, для написания...
 
Программы Delphi на заказ (236)
Пишу программы в среде Delphi на заказ http://bddelphi.ucoz.ru/
 
Пишу программы на заказ для студентов (186)
Пишу для студентов на с, с++, паскаль в средах ms visual studio, qt, builder, borland c, delphi....
 
 
 



    
rambler's top100 Rambler's Top100