Модераторы: Snowy, MetalFan, bems, Poseidon
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Деструктор выдает ошибку Invalid Pointer 
:(
    Опции темы
NeedForS
Дата 16.7.2009, 16:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 18.2.2007
Где: Город Герой - Мос ква

Репутация: нет
Всего: нет



Возникает ошибка при попытки освободить память от объекта.
Код

procedure TForm1.BitBtn9Click(Sender: TObject);
Var Dim : Dimension;
begin
 if not Assigned(Dim) then // проверяем существует Dim
  Dim := Dimension.Create;// Dim ещё не создан
 Dim.Maximum (StringGrid1, StringGrid2, StringGrid3);
 FreeAndNil(Dim);//Вот здесь ошибка
end;


Сам класс
Код

Dimension = class (TObject)
 private
  KolPerem, Var1, Var2 : Integer;
  Variable : array of boolean;
  Func, Filter, Total : array of array of Integer;
  List1, List2 : TStringList;
  procedure LoadGrid (StringGrid1, StringGrid2 : TStringGrid);
  procedure ReturnGrid (StringGrid : TStringGrid);
  procedure Filt;
  procedure Max;
  procedure Min;
  procedure Sum;
  procedure Avg;
 public
  procedure Maximum (StringGrid1, StringGrid2, StringGrid3 : TStringGrid);
  procedure Minimum (StringGrid1, StringGrid2, StringGrid3 : TStringGrid);
  procedure Amount (StringGrid1, StringGrid2, StringGrid3 : TStringGrid);
  procedure MeanArithmetic (StringGrid1, StringGrid2, StringGrid3 : TStringGrid);
end;



Текст ошибки:
Project Project1.exe raised exception class EInvalidPointer with message 'Invalid pointer operation'. Process stopped. Use Step or Run to continue.

Пробовал писать свой деструктор 
Код

destructor  Dimension.Destroy;
begin
 List1.Free;
 List2.Free;
 Finalize(Func);//Ошибка
 Finalize(Total);//Ошибка
 Finalize(Filter);//Ошибка
 Finalize(Variable);//Ошибка
end;


Добавлено через 5 минут и 48 секунд
Пробовал Dim.Free тоже не помогает
PM MAIL   Вверх
CodeMonkey
Дата 16.7.2009, 17:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 29
Всего: 89



Код
procedure TForm1.BitBtn9Click(Sender: TObject);
var
  Dim : Dimension;
begin
  Dim := Dimension.Create;
  try 
    Dim.Maximum(StringGrid1, StringGrid2, StringGrid3);
  finally
    FreeAndNil(Dim);
  end;
end;


Добавлено через 56 секунд
Вспомогательный вопрос: чему, по-вашему, равна Dim при входе в BitBtn9Click и почему?


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
NeedForS
Дата 16.7.2009, 17:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 18.2.2007
Где: Город Герой - Мос ква

Репутация: нет
Всего: нет



Да, глупо получилось, я ставлю то 
Код

procedure TForm1.BitBtn9Click(Sender: TObject);
Var Dim : Dimension;
begin
 if not Assigned(Dim) then // проверяем существует Dim
  Dim := Dimension.Create;// Dim ещё не создан
 Dim.Maximum (StringGrid1, StringGrid2, StringGrid3);
 FreeAndNil(Dim);//Вот здесь ошибка
end;

То
Код

Var Dim : Dimension;
procedure TForm1.BitBtn9Click(Sender: TObject);
begin
 if not Assigned(Dim) then // проверяем существует Dim
  Dim := Dimension.Create;// Dim ещё не создан
 Dim.Maximum (StringGrid1, StringGrid2, StringGrid3);
 FreeAndNil(Dim);//Вот здесь ошибка
end;



К сожалению 
Код

procedure TForm1.BitBtn9Click(Sender: TObject);
var
  Dim : Dimension;
begin
  Dim := Dimension.Create;
  try 
    Dim.Maximum(StringGrid1, StringGrid2, StringGrid3);
  finally
    FreeAndNil(Dim);
  end;
end;

Ситуацию не изменило. Точно та же ошибка Invalid Pointer
PM MAIL   Вверх
XperT
Дата 16.7.2009, 18:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 269
Регистрация: 19.8.2006

Репутация: нет
Всего: 4



Код

procedure TForm1.BitBtn9Click(Sender: TObject);
var
  Dim : Dimension;
begin
  Dim := Dimension.Create;
  try 
    Dim.Maximum(StringGrid1, StringGrid2, StringGrid3);
  finally
    Dim.Free;
  end;
end;


мм?
PM MAIL   Вверх
NeedForS
Дата 16.7.2009, 18:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 18.2.2007
Где: Город Герой - Мос ква

Репутация: нет
Всего: нет



Код

procedure TForm1.BitBtn9Click(Sender: TObject);
var
  Dim : Dimension;
begin
  Dim := Dimension.Create;
  try 
    Dim.Maximum(StringGrid1, StringGrid2, StringGrid3);
  finally
    Dim.Free;
  end;
end;


Тоже не помогло Invalid Pointer.

Такой вопрос, из области новичка. Ведь писать свои конуструкторы и деструкторы не обязательно, достаточно пользоваться родительскими метода Create и Free?
PM MAIL   Вверх
XperT
Дата 16.7.2009, 18:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 269
Регистрация: 19.8.2006

Репутация: нет
Всего: 4



Цитата(NeedForS @ 16.7.2009,  18:21)
Такой вопрос, из области новичка. Ведь писать свои конуструкторы и деструкторы не обязательно, достаточно пользоваться родительскими метода Create и Free?

Смотря что тебе нужно. Если нужно при создании выполнить какие-то действия или присвоить переменным какие то значения, то используй конструктор, а если ненужно - то и не используй. То же самое с деструктором.

Добавлено
Почти уверен что проблема внутри Dim.Maximum, а не на Dim.Free;

Это сообщение отредактировал(а) XperT - 16.7.2009, 18:36
PM MAIL   Вверх
NeedForS
Дата 16.7.2009, 19:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 18.2.2007
Где: Город Герой - Мос ква

Репутация: нет
Всего: нет



Цитата

Почти уверен что проблема внутри Dim.Maximum, а не на Dim.Free;

Ну вообще, я ставил паузу на строке Dim.Free до неё ошибок не возникало, после нажатия на F8 вылезает Invalid Pointer.
Привожу код Dim.Maximum. И все его вложенные методы, в процессе его выполнения. Не самый хороший по стилю код, если будут предложения как его улучшить, буду благодарен.
Код

procedure Dimension.Maximum (StringGrid1, StringGrid2, StringGrid3 : TStringGrid);
begin
 LoadGrid (StringGrid1, StringGrid2);
 if KolPerem > 2 then begin //Если количество переменных в фильтре недостаточно
  Application.MessageBox('Количество переменных в фильтре слишком маленькое','',mb_Ok);
  exit;
 end;
 Filt;
 Max;
 ReturnGrid(StringGrid3);
end;

Код

//Процедура загрузки значений StringGrid в память
procedure Dimension.LoadGrid (StringGrid1, StringGrid2 : TStringGrid);
Var  i, j, n1, n2 : integer;//i,j-переменные цикла. n1,n2-размерность массива
begin
 KolPerem := StringGrid1.ColCount - StringGrid2.RowCount - 1;
 n1 := StringGrid1.RowCount - 1;//Количество строк
 n2 := StringGrid1.ColCount - 1;//Количество столбцов
 SetLength(Func, n1, n2);
  //Задаем значения матрицы значений n-мерной функции
  for i := 0 to n1 - 1 do
    for j := 0 to n2 do
     Func[i, j] := StrToIntDef(StringGrid1.Cells[j + 1, i + 1], 0);

 n1 := StringGrid2.RowCount - 1;//Количество строк
 n2 := StringGrid2.ColCount - 1;//Количество столбцов
 SetLength(Filter, n1, n2);
  //Задаем значения матрицы значений фильтра n-мерной функции
  for i :=0 to n1 - 1 do
    for j := 0 to n2 - 1 do
     if AnsiUpperCase(StringGrid2.Cells[j + 1, i + 1]) <> 'ALL' then
      Filter[i, j] := StrToIntDef(StringGrid2.Cells[j + 1, i + 1], 0)
     else
      Filter[i, j] := -1;//Все значения
      
 n1 := StringGrid1.RowCount - 1;//Количество строк
 SetLength(Variable, n1);
 for i := 0 to n1 - 1 do
  Variable[i] := true;
end;

Код

//Процедура фильтрующая n-мерную функцию в двухмерную
procedure Dimension.Filt;
Var i, j, k : integer;//i,j,k - перменные цикла.
    flag : boolean;
begin
 //Ищем первую не фиксированную переменную
 flag := True;
 Var1 := 0;
 While flag do begin
  Var1 := Var1 + 1;
  flag := false;
  for i := 0 to High(Filter) do
   if Var1 = Filter[i, 0] then
    flag := true;
 end;
 if KolPerem = 2 then begin //Если количество переменных две то ищем вторую
  flag := True;
  Var2 := 0;
  While flag do begin
   Var2 := Var2 + 1;
   if Var2 = Var1 then Var2 := Var2 + 1;
   flag := false;
   for i := 0 to High(Filter) do
    if Var2 = Filter[i, 0] then
     flag := true;
  end;
 Var2 := Var2 - 1;
 end;
 Var1 := Var1 - 1;

 //Заполняем массив Variable если k-ый элемент равен false, то k-ая страка в массиве Func была отсеяна фильтром
 for k := 0 to High(Func) do
  for i := 0 to High(Filter) do begin
   flag := false;
   for j := 1 to High(Filter[i]) do
     if (Func[k, Filter[i, 0] - 1] =  Filter[i, j]) or (Filter[i, 1] = -1) then flag := true; //Одно из значений перменной которая находится в i-ой строке массива Filter совпало с значением этой переменной из массива Func
   if not flag then begin //Ни одно из значений перменной которая находится в i-ой строке массива Filter не совпало с значением этой переменной из массива Func
    Variable[k] := false;
    break;
   end;
  end;
//Загружаем переменные без повторений
 List1 := TStringList.Create;
 List1.Sorted := true;
 List1.Duplicates := dupIgnore;
 if KolPerem = 2 then begin
  List2 := TStringList.Create;
  List2.Sorted := true;
  List2.Duplicates := dupIgnore;
 end;
 for i := 0 to High(Variable) do
  if Variable[i] then begin
   List1.Add(IntToStr(Func[i, var1]));
   if KolPerem = 2 then
    List2.Add(IntToStr(Func[i, var2]));
  end;
 if KolPerem = 2 then
  SetLength(Total, List1.Count, List2.Count);
 if KolPerem = 1 then
  SetLength(Total, 1, List1.Count);
end;

Код

//Поиск максимального элемента на пересечение
procedure Dimension.Max;
Var i, j, n1, n2 : integer;
begin
 for i := 0 to High(Total) do
  for j := 0 to High(Total[i]) do
   Total[i,j] := 0;
 for i := 0 to High(Func) do
  if Variable[i] then
   if KolPerem = 2 then begin
    n1 := List1.IndexOf(IntToStr(Func[i, var1]));
    n2 := List2.IndexOf(IntToStr(Func[i, var2]));
    if Total[n1,n2] < Func[i, High(Func[i])] then Total[n1,n2] := Func[i, High(Func[i])];
   end
   else begin
    n1 := List1.IndexOf(IntToStr(Func[i, var1]));
    if Total[0,n1] < Func[i, High(Func[i])] then Total[0,n1] := Func[i, High(Func[i])];
   end;
end;

Код

//Возвращаем данные в таблицу  StringGrid
procedure Dimension.ReturnGrid (StringGrid : TStringGrid);
Var i, j : integer;
begin
 if KolPerem = 2 then begin
 if Total = nil then begin
  Application.MessageBox('Не было найдено ни одной функции, отвечающей запросу фильтра','',mb_Ok);
  exit;
 end;
  StringGrid.RowCount := Length(Total) + 1;
  StringGrid.ColCount := Length(Total[0]) + 1;
  StringGrid.Cells[0, 0] := 'X' + IntToStr(Var1 + 1) + '\' + 'X' + IntToStr(Var2 + 1);
  for i := 0 to List1.Count - 1 do
   StringGrid.Cells[0, i + 1] := List1[i];
  for i := 0 to List2.Count - 1 do
   StringGrid.Cells[i + 1, 0] := List2[i];
  for i := 0 to High(Total) do
   for j := 0 to High(Total[i]) do
    if Total[i, j] <> 0 then StringGrid.Cells[j + 1, i + 1] := IntToStr(Total[i, j])
    else StringGrid.Cells[j + 1, i + 1] := '';
 end;
 if KolPerem = 1 then begin
  StringGrid.Cells[0, 0] := '';
  StringGrid.RowCount := 2;
  StringGrid.ColCount := Length(Total[0]) + 1;
  StringGrid.Cells[0, 1] := 'X' + IntToStr(Var1 + 1);
  for i := 0 to List1.Count - 1 do
   StringGrid.Cells[i + 1, 0] := List1[i];
  for i := 0 to High(Total) do
   for j := 0 to High(Total[i]) do
    if Total[i, j] <> 0 then StringGrid.Cells[j + 1, i + 1] := IntToStr(Total[i, j])
    else StringGrid.Cells[j + 1, i + 1] := '';
 end;
end;

PM MAIL   Вверх
kami
Дата 16.7.2009, 19:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 22
Всего: 72



вместо Finalize попробуй SetLength(хххr, 0, 0);

P.S. создание TStringList-ов лучше вынести в конструктор, т.к. если 2 раза будет вызыван метод Maximum, то получим утечку.
Или же использовать правило "где создал, там и уничтожил".
PM MAIL WWW   Вверх
NeedForS
Дата 16.7.2009, 20:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 18.2.2007
Где: Город Герой - Мос ква

Репутация: нет
Всего: нет



Цитата

P.S. создание TStringList-ов лучше вынести в конструктор, т.к. если 2 раза будет вызыван метод Maximum, то получим утечку.
Или же использовать правило "где создал, там и уничтожил". 

Из-за того, что я не могу запустить Free я и получил утечку. А где создал там и уничтожил я не могу, так как TStringList у меня в трех методах используется.
Даже если не объявлять самому деструктор, а просто запустить Free унаследованный от TObject, то выдает ошибку Invalid Pointer. С чем это связано, я понять не могу.
PM MAIL   Вверх
NeedForS
Дата 16.7.2009, 20:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 18.2.2007
Где: Город Герой - Мос ква

Репутация: нет
Всего: нет



Попробовал использовать SetLength(Func, 0, 0) тоже самое, возникает ошибка Invalid Pointer, хотя если Watch показывает, что Func ссылается не на пустое множество
Код

destructor  Dimension.Destroy;
begin
 List1.Free;
 List2.Free;
 SetLength(Func, 0, 0);//Ошибка
 SetLength(Filter, 0, 0);//Ошибка
 SetLength(Total, 0, 0);//Ошибка
 SetLength(Variable, 0);//Ошибка
end;

PM MAIL   Вверх
kami
Дата 16.7.2009, 21:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 22
Всего: 72



Ну и заставили вы меня помучиться с вашим кодом...

ошибка здесь:

Код

  for i := 0 to n1 - 1 do
    for j := 0 to [U]n2-1[/U] do
      Func[i, j] := StrToIntDef(StringGrid1.Cells[j + 1, i + 1], 0);


Добавлено через 2 минуты и 2 секунды
для того, чтобы ее отловить нужно было просто включить rangeChecking в опциях проекта.
Но вычислил я её эмпирическим методом smile
PM MAIL WWW   Вверх
NeedForS
Дата 16.7.2009, 23:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 18.2.2007
Где: Город Герой - Мос ква

Репутация: нет
Всего: нет



Вроде все заработало так, как надо. Если возникнут ещё ошибки, я напишу. А пока все пашет на ура. Всем огромное спасибо за помощь.
PM MAIL   Вверх
CodeMonkey
Дата 17.7.2009, 08:09 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 29
Всего: 89



Цитата(NeedForS @  16.7.2009,  23:19 Найти цитируемый пост)
Если возникнут ещё ошибки, я напишу

Не надо писать. Здесь вам не тех-поддержка. Лучше сами учитесь отлаживать и исправлять ошибки.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Для новичков"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1069 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.