Текущий архив: 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.5 MB
Время: 0.037 c