Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Компоненты";
Текущий архив: 2005.07.31;
Скачать: [xml.tar.bz2];

Вниз

Ошибка во время выполнения (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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.037 c
1-1121088780
im-13
2005-07-11 17:33
2005.07.31
ошибка i/o при работе с браузером на delphi


1-1121198134
ronyn
2005-07-12 23:55
2005.07.31
Создание разделительной линии в меню.


14-1120501263
i-s-v
2005-07-04 22:21
2005.07.31
Что слушаем?


3-1118917400
ivc_andr
2005-06-16 14:23
2005.07.31
Узнать текст запроса и Host


1-1121319036
urdolphin
2005-07-14 09:30
2005.07.31
Перенаправление стандартного потока ввода вывода в Delphi





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский