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

Вниз

Ошибка во время выполнения (Self - недоступен!!)   Найти похожие ветки 

 
ViDo   (2004-07-26 21:21) [0]

Уважаемые Мастера, помогите решить следующую проблему:
 Есть класс, содержащий только простые локальные переменные
(boolean, integer) и несколько методов, обращающиеся к этим
локальным переменным, производящие несложные вычисления над
ними и выдающие результат. В процессе работы программы иногда
(приблизительно каждое сотое-двухсотое) обращение к методу
класса заканчивается ошибкой внутри метода: локальные
переменные, а также указатель Self недоступны (Inaccessible
value). Как я понимаю, если вызов метода произведен удачно
(вхождение в метод и выполнение каких-то операций произошло
успешно), то класс создан! Тогда почему может произойти такое, что локальные переменные недоступны?


 
VMcL ©   (2004-07-26 22:12) [1]

>>ViDo  (26.07.04 21:21)

Телепатов здесь нет. Код в студию.


 
Кириешки ©   (2004-07-26 22:14) [2]

>VMcL ©   (26.07.04 22:12) [1]

Полностью согласен.


 
Юрий Зотов ©   (2004-07-27 04:57) [3]

> ViDo   (26.07.04 21:21)  
> Как я понимаю, если вызов метода произведен удачно
> (вхождение в метод и выполнение каких-то операций произошло
> успешно), то класс создан!

КЛАСС создан уже тем, что Вы его объявили и реализовали его методы. Они сидят в программе в виде кода и относятся именно к самому классу, а не к его экземплярам.

Но Self (в обычных методах) указывает на ЭКЗЕМПЛЯР класса, а не на класс. Экземпляры же классов надо создавать - иначе вызвать метод будет все равно можно, но Self будет указывать неизвестно куда, а любое обращение к полям (которые Вы называете локальными переменными) даст ошибку.


 
Sandman25 ©   (2004-07-27 08:50) [4]

ИМХО это проделки оптимизатора.


 
Юрий Зотов ©   (2004-07-27 10:54) [5]

> Sandman25 ©   (27.07.04 08:50) [4]

Сначала я тоже так подумал, но задумался - а при чем тогда Self? И обратил внимание, что локальными переменными автор называет поля класса. Тогда все становится на свои места - если экземпляр класса не создан, то недоступны ни Self, ни поля.


 
Sandman25 ©   (2004-07-27 10:57) [6]

[5] Юрий Зотов ©   (27.07.04 10:54)

В таком случае велика вероятность получить AV, но необязательно, конечно.
Без кода автора может быть любой вариант.


 
Sandman25 ©   (2004-07-27 11:03) [7]

Хотя может он вообще пытается посмотреть значения Self и полей в watch window, не находясь отладчиком в методе...


 
VMcL ©   (2004-07-27 13:45) [8]

>>Юрий Зотов ©  (27.07.04 10:54) [5]

Если оптимизатор выкинул Self на каком-то этапе (то бишь затерлось значение регистра EAX, которое не сохранялось в стеке за ненадобностью), то и в этом случае поля будут недоступны, AFAIR.

В общем ждём-с автора.

>>ViDo  (26.07.04 21:21)

>Как я понимаю, если вызов метода произведен удачно
(вхождение в метод и выполнение каких-то операций произошло
успешно), то класс создан!


Неправильно понимаешь.


 
tesseract   (2004-08-01 14:51) [9]

я думаю просто спутаны понятие класс - описание объекта и объект - созданный экземпляр класса.
благодаря RTTI можно вызывать методы класса объявленные классовыми (class function) НО  поля не доступны до создания класса. Т.Е.  при старте приложения Delpi по любому создаёт таблицу методов - они есть, но объект не создан - ты просто, что-то делаешь в общем плане. Но поля класса не доступны.

B вообще переходи или на D4 или D6/7 - там шаманства на порядок меньше. D5 - вообще крайне непредсказуемая вещь.


 
Юрий Зотов ©   (2004-08-01 16:36) [10]

> tesseract   (01.08.04 14:51) [9]

> B вообще переходи или на D4 или D6/7 - там шаманства на
> порядок меньше. D5 - вообще крайне непредсказуемая вещь.

Оба-на! И чем же продиктован такой вывод?


 
Anatoly Podgoretsky ©   (2004-08-01 16:40) [11]

tesseract   (01.08.04 14:51) [9]
Так плясать нужно


 
ViDo   (2004-08-02 11:15) [12]

Уважаемые Мастера, ниже приведен код, который вызывает описанную выше ошибку.
Программа состоит из модуля DRUnit (в котором описан класс TDR) и главной программы.
В главной программе для локализации этой ошибки в цикле производится создание двух
экземпляров класса, после чего производится вычисление коэффициента корреляции между
двумя случайными массивами. Ошибка возникает от случая к случаю (в среднем один раз
на каждые сто проходов цикла) в месте, отмеченном
в коде восклицательным знаком.
 Помогите разобраться, что не так!

unit DRUnit;

interface

uses Graphics, SVConsts, Math;
const
 vMin = 1;
 vSpectrMax = 400;
type
 TBuf = array[vMin..vSpectrMax] of double;
type
 TDR = class(TObject)
 private
   FIsSKZ: boolean;
   FIsCorrect: boolean;
   FVBuf: TBuf;
 public
   property IsSKZ: boolean read FIsSKZ write FIsSKZ;
   property IsCorrect: boolean read FIsCorrect write FIsCorrect;
   constructor CreateVal(aIsSKZ: boolean; aVBuf: TBuf);
   function GetKorrelation(ADR: TDR): double;
 end;

implementation

constructor TDR.CreateVal(aIsSKZ: boolean; aVBuf: TBuf);
begin
 inherited Create;
 try
   FIsSKZ := aIsSKZ;
   FVBuf := aVBuf;
   FIsCorrect := true;
 except
   FIsCorrect := false;
 end;
end;

function TDR.GetKorrelation(ADR: TDR): double;
var M1, M2, D1, D2, Ch: double; i: word;
begin
      {!!! Вот здесь, при первом обращении к полям класса происходит ошибка    
     Значение полей FIsCorrect и FIsSKZ неопределено, так же как и
     значение Self, вызванное в Watch. При этом ADR.IsSKZ = false и
     ADR.IsCorrect = true  -  определены???}
 if not (FIsCorrect and ADR.IsCorrect and not FIsSKZ and not ADR.IsSKZ) then
   begin Result := 0; exit; end;
 M1 := Mean(FVBuf);
 M2 := Mean(ADR.VBuf);
 D1 := StdDev(FVBuf);
 D2 := StdDev(ADR.VBuf);
 Ch := 0;
 for i := Low(FVBuf) to High(FVBuf) do
   Ch := Ch + (FVBuf[i] - M1)*(ADR.FVBuf[i] - M2);
 if (D1 = 0) or (D2 = 0)
   then if (D1 + D2 = 0) then Result := 1 else Result := 0
   else Result := R2(Ch / ((D1*D2)*(High(FVBuf) - Low(FVBuf) + 1)));
end;

{Главная программа}
program SV;

uses
 DRUnit, Dialogs, Sysutils;

{$R *.RES}
var
 DR1, DR2: TDR; i: integer;
 B: TBuf;

begin
 for i := 1 to 1000 do
   begin
     for i := Lo(B) to High(B) do B[i] := Random;
     DR1 := TDR.CreateVal(false, B);
     for i := Lo(B) to High(B) do B[i] := Random;
     DR2 := TDR.CreateVal(false, B);
     try
       showmessage(FloatToStr(DR1.GetKorrelation(DR2)));
     finally
       DR2.Free;
       DR1.Free;
     end;
   end;
end.


 
Sandman25 ©   (2004-08-02 11:24) [13]

for i := 1 to 1000 do
  begin
    for i := Lo(B) to High(B) do B[i] := Random;

Это как?
Кстати, не Lo, а Low. Разница огромна.


 
Sandman25 ©   (2004-08-02 11:33) [14]

Вот так у меня работает без всяких ошибок:

for i := 1 to 1000 do
  begin
    for j := Low(B) to High(B) do B[j] := Random;
    DR1 := TDR.CreateVal(false, B);
    for j := Low(B) to High(B) do B[j] := Random;
    DR2 := TDR.CreateVal(false, B);
    try
      if (FloatToStr(DR1.GetKorrelation(DR2)))="11" then
        ShowMessage("1");
    finally
      DR2.Free;
      DR1.Free;
    end;
  end;

function TDR.GetKorrelation(ADR: TDR): double;
var M1, M2, D1, D2, Ch: double; i: word;
begin
if not (FIsCorrect and ADR.IsCorrect and not FIsSKZ and not ADR.IsSKZ) then
result := 0
else
Result :=1;
end;


 
Sandman25 ©   (2004-08-02 11:39) [15]

Кстати, зачем рассчитывать Ch в том случае, если оно не используется?


 
ViDo   (2004-08-02 15:32) [16]

>Кстати, зачем рассчитывать Ch в том случае, если оно не используется?
  Логично, спасибо за подсказку.
>Кстати, не Lo, а Low. Разница огромна
 Конечно, Low. Это просто опечатка - я перепечатывал код (именно, перепечатывал, а не переносил), потому что весь модуль DRUnit содержит порядка 3 тысяч строк.
>Вот так у меня работает без всяких ошибок
 Так я о чем и говорю, что у меня ошибка появляется давольно редко, но ПОЯВЛЯЕТСЯ.
 Хоть по теории объясните, чем, в принципе, это может быть вызвано, а я уже буду искать!!!


 
Anatoly Podgoretsky ©   (2004-08-02 15:40) [17]

Вот это безобразие
begin
for i := 1 to 1000 do
  begin
    for i := Lo(B) to High(B) do B[i] := Random;


 
Sandman25 ©   (2004-08-02 15:47) [18]

[16] ViDo   (02.08.04 15:32)

Ошибка не в приведенном коде.
Заменил упрощенный код TDR.GetKorrelation на Ваш исходный код (кроме функции R2):

if not (FIsCorrect and ADR.IsCorrect and not FIsSKZ and not ADR.IsSKZ) then
  begin Result := 0; exit; end;
M1 := Mean(FVBuf);
M2 := Mean(ADR.VBuf);
D1 := StdDev(FVBuf);
D2 := StdDev(ADR.VBuf);
Ch := 0;
for i := Low(FVBuf) to High(FVBuf) do
  Ch := Ch + (FVBuf[i] - M1)*(ADR.FVBuf[i] - M2);
if (D1 = 0) or (D2 = 0)
  then if (D1 + D2 = 0) then Result := 1 else Result := 0
  else Result := Ch / ((D1*D2)*(High(FVBuf) - Low(FVBuf) + 1));;

все равно никакой ошибки даже за 10000 итераций.

Если нужна помощь, нужно не перепечатывать, а копировать. Желательно все, относящееся к проблеме.



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

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

Наверх




Память: 0.52 MB
Время: 0.079 c
4-1117796672
webpauk
2005-06-03 15:04
2005.07.31
Указатели и DirectDraw


1-1121252021
ZSergey
2005-07-13 14:53
2005.07.31
почему компилятор пропускает строки?


6-1113999635
COOLer
2005-04-20 16:20
2005.07.31
Помогите с поиском сервера


1-1121225231
AZ
2005-07-13 07:27
2005.07.31
TThread. Можно ли внутри процедуры Execute делать Suspend?


14-1120667429
Kerk
2005-07-06 20:30
2005.07.31
Язык для шаманов