![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Ошибка во время выполнения (Self - недоступен!!) [D5, Win95/98]
ViDo © (2004-07-26 21:21:00)Уважаемые Мастера, помогите решить следующую проблему:
Есть класс, содержащий только простыелокальные переменные
(boolean, integer) и несколько методов, обращающиеся к этим
локальным переменным, производящие несложные вычисления над
ними и выдающие результат. В процессе работы программы иногда
(приблизительно каждое сотое-двухсотое) обращение к методу
класса заканчивается ошибкой внутри метода: локальные
переменные, а также указатель Self недоступны (Inaccessible
value). Как я понимаю, если вызов метода произведен удачно
(вхождение в метод и выполнение каких-то операций произошло
успешно), то класс создан! Тогда почему может произойти такое, что локальные переменные недоступны?
Sandman25 (2004-08-02 15:47:00) [1][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 итераций.
Если нужна помощь, нужно не перепечатывать, а копировать. Желательно все, относящееся к проблеме.
Anatoly Podgoretsky (2004-08-02 15:40:00) [2]Вот это безобразие
begin
for i :=1 to 1000 do
begin
for i :=Lo(B) to High(B) do B[i] := Random;
ViDo (2004-08-02 15:32:00) [3]>Кстати, зачем рассчитывать Ch в том случае, если оно не используется?
Логично, спасибо за подсказку.
>Кстати, не Lo, а Low. Разница огромна
Конечно, Low. Это просто опечатка - я перепечатывал код (именно, перепечатывал, а не переносил), потому что весь модуль DRUnit содержит порядка 3 тысяч строк.
>Вот так у меня работает без всяких ошибок
Так я о чем и говорю, что у меня ошибка появляется давольно редко, но ПОЯВЛЯЕТСЯ.
Хоть по теории объясните, чем, в принципе, это может быть вызвано, а я уже буду искать!!!
Sandman25 (2004-08-02 11:39:00) [4]Кстати, зачем рассчитывать Ch в том случае, если оно не используется?
Sandman25 (2004-08-02 11:33:00) [5]Вот так у меня работает без всяких ошибок:
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:24:00) [6]for i := 1 to 1000 do
begin
for i := Lo(B) to High(B) do B[i] := Random;
Это как?
Кстати, не Lo, а Low. Разница огромна.
ViDo (2004-08-02 11:15:00) [7]Уважаемые Мастера, ниже приведен код, который вызывает описанную выше ошибку.
Программа состоит из модуля 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.
Anatoly Podgoretsky (2004-08-01 16:40:00) [8]tesseract (01.08.04 14:51) [9]
Так плясать нужно
Юрий Зотов (2004-08-01 16:36:00) [9]> tesseract (01.08.04 14:51) [9]
> B вообще переходи или на D4 или D6/7 - там шаманства на
> порядок меньше. D5 - вообще крайне непредсказуемая вещь.
Оба-на! И чем же продиктован такой вывод?
tesseract (2004-08-01 14:51:00) [10]я думаю просто спутаны понятие класс - описание объекта и объект - созданный экземпляр класса.
благодаря RTTI можно вызывать методы класса объявленные классовыми (class function) НО поля не доступны до создания класса. Т.Е. при старте приложения Delpi по любому создаёт таблицу методов - они есть, но объект не создан - ты просто, что-то делаешь в общем плане. Но поля класса не доступны.
B вообще переходи или на D4 или D6/7 - там шаманства на порядок меньше. D5 - вообще крайне непредсказуемая вещь.
VMcL (2004-07-27 13:45:00) [11]>> Юрий Зотов © (27.07.04 10:54) [5]
Если оптимизатор выкинул Self на каком-то этапе (то бишь затерлось значение регистра EAX, которое не сохранялось в стеке за ненадобностью), то и в этом случае поля будут недоступны, AFAIR.
В общем ждём-с автора.
>> ViDo (26.07.04 21:21)
> Как я понимаю, если вызов метода произведен удачно
(вхождение в метод и выполнение каких-то операций произошло
успешно), то класс создан!
Неправильно понимаешь.
Sandman25 (2004-07-27 11:03:00) [12]Хотя может он вообще пытается посмотреть значения Self и полей в watch window, не находясь отладчиком в методе...
Sandman25 (2004-07-27 10:57:00) [13][5] Юрий Зотов © (27.07.04 10:54)
В таком случае велика вероятность получить AV, но необязательно, конечно.
Без кода автора может быть любой вариант.
Юрий Зотов (2004-07-27 10:54:00) [14]> Sandman25 © (27.07.04 08:50) [4]
Сначала я тоже так подумал, но задумался - а при чем тогда Self? И обратил внимание, что локальными переменными автор называет поля класса. Тогда все становится на свои места - если экземпляр класса не создан, то недоступны ни Self, ни поля.
Sandman25 (2004-07-27 08:50:00) [15]ИМХО это проделки оптимизатора.
Юрий Зотов (2004-07-27 04:57:00) [16]> ViDo (26.07.04 21:21)
> Как я понимаю, если вызов метода произведен удачно
> (вхождение в метод и выполнение каких-то операций произошло
> успешно), то класс создан!
КЛАСС создан уже тем, что Вы его объявили и реализовали его методы. Они сидят в программе в виде кода и относятся именно к самому классу, а не к его экземплярам.
Но Self (в обычных методах) указывает на ЭКЗЕМПЛЯР класса, а не на класс. Экземпляры же классов надо создавать - иначе вызвать метод будет все равно можно, но Self будет указывать неизвестно куда, а любое обращение к полям (которые Вы называете локальными переменными) даст ошибку.
Кириешки (2004-07-26 22:14:00) [17]>VMcL © (26.07.04 22:12) [1]
Полностью согласен.
VMcL (2004-07-26 22:12:00) [18]>>ViDo (26.07.04 21:21)
Телепатов здесь нет. Код в студию.