Правильный free

Давняя и застарелая проблема.
Если на один объект есть несколько ссылок, то освобождение его с помощью одной ссылки ничего не делает с другими.
В смысле по другим ссылкам к нему по прежнему можно обращаться и во многих случаях результат будет, как будто никто его и не освобождал.
Специально написал простенький тест
pas
lfm
Кнопкой Create создается объект и на него делается вторая ссылка.
Кнопкой Free первая ссылка освобождается
Кнопкой Read выводится содержимое объекта по второй ссылке. Легко убедится, что Read прекрасно работает после Free.
На разных платформах и в среде Delphi.
Меня удивляет не столько наличие проблемы, сколько отсутствие даже ее обсуждения.
Со своей стороны хочу предложить, чтобы при освобождении объекта , обнулялся его указатель self. Я попробовал это сделать самостоятельно, но при этой операции программа иногда падает, а иногда все равно все работает (правда, содержимое портится, но это несущественно).
Ну и понятно, что это должно делаться на системном уровне.
Если на один объект есть несколько ссылок, то освобождение его с помощью одной ссылки ничего не делает с другими.
В смысле по другим ссылкам к нему по прежнему можно обращаться и во многих случаях результат будет, как будто никто его и не освобождал.
Специально написал простенький тест
pas
- Код: Выделить всё
unit UfmTestFreeError;
{$MODE Delphi}
{$OBJECTCHECKS+}
interface
uses
LCLIntf, LCLType, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, MaskEdit;
type
TSimpleInt = class
public
Value: integer;
constructor Init(V: integer);
destructor Destroy; override;
end;
{ TfmTestFreeError }
TfmTestFreeError = class(TForm)
bnCreate: TBitBtn;
edResult: TEdit;
bnRead: TBitBtn;
Label1: TLabel;
Label2: TLabel;
medSource: TMaskEdit;
bnFree: TBitBtn;
procedure bnCreateClick(Sender: TObject);
procedure bnReadClick(Sender: TObject);
procedure bnFreeClick(Sender: TObject);
private
{ Private declarations }
SimpleInt: TSimpleInt;
SimpleRef: TSimpleInt;
public
{ Public declarations }
end;
var
fmTestFreeError: TfmTestFreeError;
implementation
{$R *.lfm}
{ TSimpleInt }
constructor TSimpleInt.Init(V: integer);
begin
inherited Create;
Value := V;
end;
destructor TSimpleInt.Destroy;
begin
inherited;
//Self := nil;
end;
procedure TfmTestFreeError.bnReadClick(Sender: TObject);
begin
edResult.Text := IntToStr(SimpleRef.Value);
end;
procedure TfmTestFreeError.bnCreateClick(Sender: TObject);
begin
SimpleInt := TSimpleInt.Init(StrToInt(medSource.Text));
SimpleRef := SimpleInt;
end;
procedure TfmTestFreeError.bnFreeClick(Sender: TObject);
begin
FreeAndNil(SimpleInt);
end;
end.
lfm
- Код: Выделить всё
object fmTestFreeError: TfmTestFreeError
Left = 436
Height = 147
Top = 200
Width = 528
Caption = 'Test Free Error'
ClientHeight = 147
ClientWidth = 528
Color = clBtnFace
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
LCLVersion = '1.6.2.0'
object edResult: TEdit
Left = 64
Height = 21
Top = 48
Width = 121
TabOrder = 0
end
object bnRead: TBitBtn
Left = 312
Height = 25
Top = 56
Width = 121
Caption = 'Read'
OnClick = bnReadClick
TabOrder = 1
end
object medSource: TMaskEdit
Left = 64
Height = 21
Top = 16
Width = 120
CharCase = ecNormal
MaxLength = 5
TabOrder = 2
EditMask = '!99999;1;_'
Text = ' '
SpaceChar = '_'
end
object bnFree: TBitBtn
Left = 312
Height = 25
Top = 96
Width = 121
Caption = 'Free'
OnClick = bnFreeClick
TabOrder = 3
end
object Label1: TLabel
Left = 8
Height = 13
Top = 20
Width = 32
Caption = 'Число'
ParentColor = False
end
object Label2: TLabel
Left = 8
Height = 13
Top = 56
Width = 52
Caption = 'Результат'
ParentColor = False
end
object bnCreate: TBitBtn
Left = 312
Height = 25
Top = 16
Width = 121
Caption = 'Create'
OnClick = bnCreateClick
TabOrder = 4
end
end
Кнопкой Create создается объект и на него делается вторая ссылка.
Кнопкой Free первая ссылка освобождается
Кнопкой Read выводится содержимое объекта по второй ссылке. Легко убедится, что Read прекрасно работает после Free.
На разных платформах и в среде Delphi.
Меня удивляет не столько наличие проблемы, сколько отсутствие даже ее обсуждения.
Со своей стороны хочу предложить, чтобы при освобождении объекта , обнулялся его указатель self. Я попробовал это сделать самостоятельно, но при этой операции программа иногда падает, а иногда все равно все работает (правда, содержимое портится, но это несущественно).
Ну и понятно, что это должно делаться на системном уровне.