Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.01.29;
Скачать: CL | DM;

Вниз

Народ, я уже не могу, я щасойду сума   Найти похожие ветки 

 
dust ©   (2006-01-04 13:34) [0]

Я уже часа три бьюсь на сотней строчек кода. И не могу не могу понять почему я в деструкторе ошибку получаю.
Как можно вообще получить ошибку в деструкторе при вызове Inherited!??? Особенно учитывая, что объект наследовался от TObject, тем более эксцепшн Invalid Pointer Operation.


 
Virgo_Style ©   (2006-01-04 13:37) [1]

dust ©   (04.01.06 13:34)
Как можно вообще


Программа твоя, тебе виднее. Покажешь деструктор - может и мы узнаем.


 
umbra ©   (2006-01-04 13:38) [2]

а отладить с заходом в Inherited?


 
Kerk ©   (2006-01-04 13:38) [3]

Отвечает Александр Друзь...


 
Гаврила ©   (2006-01-04 13:40) [4]

вариантов много
может быть, объект уже разрушен
может быть, он и не был создан
Он у тебя виртуальный, деструктор?


 
dust ©   (2006-01-04 13:42) [5]

Так что код показывать? Посмотрите свежим взглядом?


 
Игорь Шевченко ©   (2006-01-04 13:47) [6]


> Так что код показывать?


Зачем ? Дай поупражняться в телепатии


 
Virgo_Style ©   (2006-01-04 13:48) [7]

dust ©   (04.01.06 13:42) [5]

Предлагаю начать новую ветку под названием "стоит ли dust"у показывать свой код?"

P.S. Что-то злой я какой-то сегодня. Извини, если что :-) Покажи, конечно. Хотя зачем в "потрепаться" писал...


 
Думкин ©   (2006-01-04 13:50) [8]

Остановите Землю. Я сойду.

Но вы на Луне.

А.. сойти то мне надо на Землю. И Луну остановите тоже.


 
tesseract ©   (2006-01-04 13:50) [9]


>  ошибку в деструкторе при вызове Inherited!???

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


 
dust ©   (2006-01-04 13:52) [10]

type aDword = packed array [0..31] of dword;
type aByte  = packed array [0..1024*16-1] of byte;

procedure TForm1.Button1Click(Sender: TObject);
var
   Chain1         : TChain;
   i,j,k    : INteger;
   aData    : aByte;
   aDWD      : ^aDword;
begin
 aDWD := Pointer(@aData);
 Chain1 := TChain.Create(1024*16);
 k:=1;
 for i:=1 to k do
   begin
   for j:= 0 to 30 do
    aDWD^[j] := Random(513);
   Chain1.Append(aData);
   end;
 chain1.Destroy;
end;


 
dust ©   (2006-01-04 13:53) [11]

unit Chains;

interface
uses Windows, SysUtils;
type
PChainRec = ^TChainRec;
TChainRec = record
  Prev,
  Next  : PChainRec;
  Data  : Pointer;
  end;
//***********************************************************************
//***********************************************************************
//***********************************************************************
TChain = class(TObject)
  private
    { Private declarations }
    ItemSize : Integer;

    First, //первый, последний и текущий элементы цепочки
    Last,
    Current,
            //Bookmark
    OldPosition : PChainRec;
    FEmptyFlag  : boolean;
    //procedure GetLastBranch (var Branch : TChainRec)
    function GetData(const item: Pointer): Pointer;
  public
    { Public declarations }
    Count       : Integer; //текущее Колличество элементов в списке

      {Конструктор и деструктор}
      constructor Create (const DataSize : Integer);
      destructor Destroy(); override;

    procedure Append   (const item); //добавляет в конец цепочки
    procedure AddFirst (const item); //добавляет в начало цепочки
    procedure Delete(); //удаляет текущий элемент делая текущим следующий
    procedure Clear();  //очищает цепочку

    //базовая Навигация по списку
    procedure Prev();   //делает текущим предыдущий элемент
    procedure Next();   //делает текущим следующий элемент
    //расширенная навигация по списку
    procedure GoFirst();  //делает текущим первый элемент
    procedure GoLast();   //делает текущим последний элемент
    procedure RememberPos();  //запоминает текущий элемент,,, (!)будьте осторожны(!)
    procedure RestorePos();   //восстанавливает текущий элемент,,,(!)будьте осторожны(!)

    function  GetCurrent(): Pointer; //выдаёт указатель на текущий элемент в списке
    function  IsFirst()   : boolean; //?????проверяет, является ли текущий списка последним
    function  IsLast()    : boolean; //?????проверяет, является ли текущий списка последним
    function  IsEmpty()   : boolean; //?????проверяет, является ли текущий списка последним
  end;

implementation

{ TChain }
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

constructor TChain.Create (const DataSize : Integer);
begin
 inherited Create();
 ItemSize := DataSize;
 FEmptyFlag:=true;
 Count := 0;
end;
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

procedure TChain.AddFirst(const item);
var  tmpBranch :  PChainRec;
begin
new(tmpBranch);
if FEmptyFlag then
  begin
  FEmptyFlag := false;
  Last    := tmpBranch;
  Current := tmpBranch;
  end;

tmpBranch.Prev := Last; //список циклический
tmpBranch.Next := First;
tmpBranch.Data := GetData(@item);
First.Prev := tmpBranch;
First := tmpBranch;
inc(Count);
end;
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

procedure TChain.Append(const item);
var  tmpBranch  :  PChainRec;
    tmpCurrent :  PChainRec;
begin
new(tmpBranch);
tmpBranch.Data := GetData(@item);

if FEmptyFlag then
  begin
  FEmptyFlag := false;
  First := tmpBranch;
  Last  := tmpBranch;
  Current := tmpBranch;
  end;

tmpCurrent := Last;
tmpCurrent.Next   := tmpBranch; //Список циклический
tmpBranch.Prev := tmpCurrent;
inc(Count);
end;
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

procedure TChain.Clear;
var  tmpBranch :  PChainRec;
begin
if FEmptyFlag then Exit;
tmpBranch := First;
while assigned(tmpBranch.Next) do
  begin
  FreeMem(tmpBranch.Data); tmpBranch.Data := nil;

  tmpBranch := tmpBranch.Next;

  Dispose(tmpBranch.Prev); tmpBranch.Prev := nil;
 // dec(count);
  if tmpBranch = Last then
      break;
  end;
Count   := 0;
Current := nil;
FEmptyFlag := true;
First := nil;
Last  := nil;
end;
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

procedure TChain.Delete;
var  tmpBranch :  PChainRec;
begin
if FEmptyFlag then exit;
if assigned(Current) then
  begin
  tmpBranch := Current.Next;
  Dispose (Current);
  Current  :=tmpBranch;
  dec(Count);
  end
end;
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

destructor TChain.Destroy;
begin
 Clear();
 inherited;
end;
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

function TChain.GetCurrent: Pointer;
begin
if not assigned(Current)then
  Result := nil
 else
  Result := Current.Data;
end;
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

function TChain.IsEmpty: boolean;
begin
Result := FEmptyFlag;
end;
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

function TChain.IsFirst: boolean;
begin
Result := Current = First;
end;
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

function TChain.IsLast: boolean;
begin
Result := Current = Last;
end;
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

procedure TChain.Next;
begin
if not assigned (Current) then
  begin
  MessageBox (0, "", nil, MB_OK or MB_ICONHAND);
  Exit;
  end;
if assigned(Current.Next) then
  Current := Current.Next;
end;
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

procedure TChain.Prev;
begin
if not assigned (Current) then
  begin
  MessageBox (0, "", nil, MB_OK or MB_ICONHAND);
  Exit;
  end;
if assigned(Current.Prev) then
  Current := Current.Prev;
end;
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

procedure TChain.RememberPos;
begin
OldPosition := Current;
end;
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

procedure TChain.RestorePos;
begin
Current := OldPosition;
end;
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

procedure TChain.GoFirst();
begin
Current := First;
end;
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

procedure TChain.GoLast();
begin
 Current := Last;
end;
//=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

function TChain.GetData(const item: Pointer): Pointer;

begin
Result := AllocMem(ItemSize);
Move (item^, Result^, ItemSize); // (source, destination, CountBites)
end;

end.


 
tesseract ©   (2006-01-04 13:58) [12]

Не нравятся мне вызывы AllocMem и system.Move одновременно. Используй New/Dispose.

А точно нужно получать в GetData новый указатель? Возможны  проблемы с утечкой.


 
begin...end ©   (2006-01-04 13:59) [13]

> tesseract ©   (04.01.06 13:50) [9]

И что ужасного в вызове inherited в начале деструктора?


 
tesseract ©   (2006-01-04 14:02) [14]


> И что ужасного в вызове inherited в начале деструктора?

Проблема была. С тех пор сначала освободжаю выделенную память до inherited.


 
Marser ©   (2006-01-04 14:13) [15]


> И что ужасного в вызове inherited в начале деструктора?

По моему разумению в том, что объект освобождается в inherited destroy, после чего обращение к его полям и методам должно вызвать AV. Или я чего-то не учитываю?


 
begin...end ©   (2006-01-04 14:14) [16]

> tesseract ©   (04.01.06 14:02) [14]

Ничего не понял.

type
 TAncestor = class
   FByte: PByte;
   constructor Create;
   destructor Destroy; override;
 end;

 TDescendant = class(TAncestor)
   FWord: PWord;
   constructor Create;
   destructor Destroy; override;
 end;

{ TAncestor }

constructor TAncestor.Create;
begin
 New(FByte)
end;

destructor TAncestor.Destroy;
begin
 Dispose(FByte)
end;

{ TDescendant }

constructor TDescendant.Create;
begin
 inherited;
 New(FWord)
end;

destructor TDescendant.Destroy;
begin
 inherited;
 Dispose(FWord)
end;


Создаём и уничтожаем экземпляры TDescendant до посинения. Ошибок, вопреки [9], не происходит.


 
tesseract ©   (2006-01-04 14:21) [17]

Может и не происходить а может и происходить. Зависит от того сколько и чего освобождаешь. То что этот был косяк практически замечен - факт.

Насчёт AllocMem - ошибался. Он работает в данном контексте.


 
Игорь Шевченко ©   (2006-01-04 14:25) [18]


> По моему разумению в том, что объект освобождается в inherited
> destroy, после чего обращение к его полям и методам должно
> вызвать AV. Или я чего-то не учитываю?


Какой объект ?


 
umbra ©   (2006-01-04 14:28) [19]

ошибка вылетает где-то в GetMem.inc при освобождении памяти кучи и происходит это после выполнения метода Clear.


 
begin...end ©   (2006-01-04 14:30) [20]

> Marser ©   (04.01.06 14:13) [15]

Объект как экземпляр класса уничтожается после отработки своего деструктора. Вызовы унаследованных деструкторов приводят лишь к исполнению их кода (между begin и end), но не к уничтожению объекта.

Другое дело, что если я вызвал какой-нибудь inherited-деструктор, в котором освободил некий ресурс (например, динамически выделенную память), то дальше я уже не могу этим ресурсом пользоваться. Например, в [16] после вызова унаследованного деструктора из TDescendant.Destroy я не могу обращаться к FByte^, потому что уже было Dispose(FByte), но само поле FByte, конечно, никуда не делось -- экземпляр класса пока не разрушен.

> tesseract ©   (04.01.06 14:21) [17]
> То что этот был косяк практически замечен - факт.

Косяк был из-за криворукости.


 
tesseract ©   (2006-01-04 14:39) [21]


> Косяк был из-за криворукости.


Из-за многопоточности:-) Уничтожался другой объект - критическая секция.Которая кое-где в потоке ещё не сработала.  


> ошибка вылетает где-то в GetMem.inc при освобождении памяти
> кучи и происходит это после выполнения метода Clear.

Я про то же.


 
Игорь Шевченко ©   (2006-01-04 14:41) [22]

begin...end ©   (04.01.06 14:30) [20]


> Объект как экземпляр класса уничтожается после отработки
> своего деструктора


Объект уничтожается процедурой FreeInstance, вызываемой в конце выполнения деструктора, если деструктор вызван явно, а не по inherited.

TObject.Destroy (Self: TObject, NotInherited: Integer);
begin
 BeforeDestruction;
 if NotInherited > 0 then
   _ClassDestroy (Self);
end;

procedure _ClassDestroy (TObject: Instance);
begin
 Instance.ClassType.FreeInstance (Instance);
end;


 
begin...end ©   (2006-01-04 14:45) [23]

> Игорь Шевченко ©   (04.01.06 14:41) [22]

Ну, и? Я что-то не так сказал?


 
jack128 ©   (2006-01-04 14:46) [24]

dust ©   (04.01.06 13:53) [11]
tmpCurrent.Next   := tmpBranch; //Список циклический

Да не циклический это список. Это вообще ХЗ что. Last.Next - вообще указывает непонятно на что, потому что ты это поле не инициализируешь. В циклическом списке, последний элемент указывает на первый! Вот и всё. Зачем тебе в ЦИКЛИЧЕСКОМ списке поля First и Last - вообще не понятно.  На вскидку - у тебя здесь не доделанный двухсвязный, не циклический список. Кольцом здесь не пахнет. Зачем поле здесь FEmptyFlag - тооже не понятно, нужно заменить его функцией function TChain.IsEmpty: boolean; begin Result := Assigned(First) end;
вобщем скорее всего проблема связана с неинициализацией поля Next твоей записи, разбираться подробнее - лень. Проще написать как должно быть:

procedure TChain.Append(const item);
var
 tmpBranch: PChainRec;
begin
 New(tmpBranch);
 tmpBranch.Data := GetData(@item);
 tmpBranch.Prev := Last;
 tmpBranch.Next := nil;
 if Assigned(Last) then
   Last.Next := tmpBranch;
 Last := tmpBranch;
 if not Assigned(First) then
   First := tmpBranch;
 Inc(Count);
end;

procedure TChain.Clear;
var
 tmpBranch, nextBranch:  PChainRec;
begin
 tmpBranch := First;
 while Assigned(tmpBranch) do
 begin
   nextBranch := tmpBranch.Next;
   FreeMem(tmpBranch.Data);
   Dispose(tmpBranch);
   tmpBranch := nextBranch;
 end;
 Count := 0;
 First := nil;
 Last := nil;
end;


PS названия всех полей должны начинаться в префикса F, а названия типов - в префикса T, а за использование такой конструкции - Chain1 := TChain.Create(1024*16); тебя зарезать тупым ножом мало - только SizeOf и никак иначе.


 
dust ©   (2006-01-04 14:46) [25]

Так ктонить чтонить понял????? Я лично понять не могу... :(
Я уже дошёл до отладки модуля систем, и лично для меня загадка, почему

procedure _ClassDestroy(Instance: TObject);
begin
 Instance.FreeInstance;
end;

вызывает ошибку.... притом такую странную
       heapErrorCode := cBadNextBlock;


 
tesseract ©   (2006-01-04 14:46) [26]

TChainRec = record  
                           Prev,  Next  : PChainRec;
                            Data  : Pointer;  
                end;

Не понял ???

Ссылку на себя через себя? Ты же можешь освободить память чему нибудь другому. Попробуй проверять перед освобождением Assigned.


 
Игорь Шевченко ©   (2006-01-04 14:53) [27]

begin...end ©   (04.01.06 14:45) [23]

Да нет, все так. Я просто счел нужным дополнить.

С наступившим!


 
umbra ©   (2006-01-04 14:57) [28]

а зачем метод Clear нужен, если есть несколько недоделанный Delete? Зачем в Clear проверять на Assigned, если есть прекрасное свойство Count?
Вот поправленные Clear и Delete. Ошибка не происходит

procedure TChain.Delete;
var  tmpBranch :  PChainRec;
begin
if FEmptyFlag then exit;
if assigned(Current) then
 begin
 tmpBranch := Current.Next;
 FreeMem(Current.Data);
 Dispose (Current);
 Current  :=tmpBranch;
 dec(Count);
 end
end;

procedure TChain.Clear;
var  tmpBranch :  PChainRec;
begin
if FEmptyFlag then Exit;
Current := First;
while Count > 0 do
 begin
   Delete;
   dec(count);
 end;
FEmptyFlag := true;
end;



 
umbra ©   (2006-01-04 14:59) [29]

Пардон, не досмотрел

procedure TChain.Clear;
begin
if FEmptyFlag then Exit;
Current := First;
while Count > 0 do
  Delete;
FEmptyFlag := true;
end;


 
begin...end ©   (2006-01-04 15:08) [30]

> Игорь Шевченко ©   (04.01.06 14:53) [27]
> С наступившим!

Спасибо, Вас тоже :)



Страницы: 1 вся ветка

Текущий архив: 2006.01.29;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.045 c
2-1137366701
Лом
2006-01-16 02:11
2006.01.29
Stringgrid


15-1136754461
DillerXX
2006-01-09 00:07
2006.01.29
Клиническая смерть


15-1135690725
Holy
2005-12-27 16:38
2006.01.29
Новогодняя БМП (Belgorod MP)


10-1099987341
mak
2004-11-09 11:02
2006.01.29
проблемы вызова COM сервера в WIN2003


2-1137152908
SarDoX
2006-01-13 14:48
2006.01.29
IE и delphi