Текущий архив: 2004.08.08;
Скачать: CL | DM;
ВнизЭкземпляр класса в качестве свойства другого класса Найти похожие ветки
← →
DeScriptor (2004-07-22 19:40) [0]Можно ли делать сабж? То есть, иными словами, так:
TMyClass1=class
public
AnyProperty: TMyClass2;
Я попытался использовать подобную конструкцию (с той лишь разницей, что используется динамический массив экземпляров), и компилятор ничего плохого в том не заметил, но почему-то во время выполнения попытка создать экземпляр класса приводит к Access Violation. =(
Создаю я экземпляр следующим образом (type TClassArray=array ofTMyClass2; var ExArray: TClassArray;
):
...
ExArray[i]:=TMyClass1.Create; // Здесь и происходит AV
...
Я подозреваю невозможность так поступать потому, что массив классов (такой же) работает в другом месте, создается вне класса, просто как переменная.
← →
DeScriptor (2004-07-22 19:42) [1]P.S. Опечатался:
...
ExArray[i]:=TMyClass2.Create; // Здесь и происходит AV
...
← →
Суслик © (2004-07-22 19:44) [2]уверен,
1. что у тебя отключен rangecheck error в опциях проекта.
2. ты не делаешь setlength для exarray
← →
AlexG © (2004-07-22 23:51) [3]Действительно, проверь то о чем тебе говорит Суслик.
PS: Пока Кролик с Вини-Пухом не пришли, лучше ешь мёд... Пятачок тебе не помешает :Р
← →
DeScriptor (2004-07-23 01:52) [4]Ну, все-таки я, наверное, не настолько тупой, чтобы писать в массив, длина которого не задана! =) Просто, я подумал, что это здесь писать будет излишне. Да и range-checking у меня всегда включен, т.к. я прекрасно знаю свою слабость ошибаться на единичку. Так что, проблема в чем-то другом.
← →
ЮЮ © (2004-07-23 04:55) [5]>Ну, все-таки я, наверное, не настолько тупой ...
А мы, к сожалению, не настолько умны, чтобы увидеть причмну AV, глядя на TMyClass2.Create; Приведи тогда код конструктора.
P.S. А по поводу Subj-а. Ради бога. Тип полей может быть каким укодно из известных в этом модуле
P.P.S. Вот только поля, IMHO, должны находиться в private, а не в public секции
← →
АлексейК (2004-07-23 06:44) [6]
type
TMyClass1=class
public
AnyProperty: TMyClass2;
...
end;
TClassArray=array ofTMyClass2;
var ExArray: TClassArray;
...
ExArray[i]:=TMyClass1.Create; // Здесь и происходит AV
P.S. Опечатался:ExArray[i]:=TMyClass2.Create; // Здесь и происходит AV
В таком случае причем тут TMyClass1? Следовательно вопрос становися непонятным, какое отношение имеет к нему тип поля объекта?
Поробуйте так.
ExArray[i]:=nil;
Если ошибка возникает и память под массив выделена была, то скорее всего происходит банальный выход за пределы диапазона массива.
← →
Ega23 © (2004-07-23 09:42) [7]ИМХО, порочный путь использовать динамический массив классов. Используй TObjectList.
← →
Суслик © (2004-07-23 11:18) [8]автор, у тебя нет другого выхода, кроме как расколоться и привести полный текст tmyclass1.create
← →
DeScriptor (2004-07-23 14:52) [9]Ну, что ж, приведу весь код ОДНОГО класса (в котором баг происходит, в моем примере выступал в роли TMyClass1, тот, что я образно обозвал TMyClass2, работает без проблем вообще).
unit ResProcessingCode;
interface
uses
Classes, ResHeaderClassCode, SysUtils;
const
RP_SCAN=Byte(1);
RP_EXTR=Byte(2);
RP_PACK=Byte(3);
type
TEntriesListElement=record
Offset:longword;
Extension:string[8];
end;
THdrArray=array of TResHeader;
TResProcessing = class(TThread)
private
EntriesList: array of TEntriesListElement;
EntriesFile: file of TEntriesListElement;
HeadersList: THdrArray;
ResFile:file;
LastBarPos, CurBarPos:word;
CurFilePos, MaxFilePos:longword;
LogEvent:string;
procedure ScanResFile();
procedure ExtractFiles();
procedure PackFiles();
procedure UpdateProgBar();
procedure UpdateLog();
public
JobID:byte;
procedure SetHeadersList(HeadersToProcess: THdrArray);
procedure ResetEngine(FileName:string; HeadersToProcess: THdrArray);
constructor Create(FileName:string; HeadersToProcess: THdrArray);
destructor Destroy(); override;
protected
procedure Execute(); override;
end;
implementation
uses MainWinCode;
procedure TResProcessing.UpdateLog();
begin
MainWinCode.UpdateLog(LogEvent);
end;
procedure TResProcessing.ResetEngine(FileName:string; HeadersToProcess: THdrArray);
begin
JobID:=RP_SCAN;
if EntriesList<>nil then EntriesList:=nil;
SetHeadersList(HeadersToProcess);
AssignFile(ResFile,FileName);
Reset(ResFile,1);
MaxFilePos:=FileSize(ResFile);
CurBarPos:=0;
Synchronize(UpdateProgBar);
end;
procedure TResProcessing.UpdateProgBar();
begin
LastBarPos:=CurBarPos;
CurBarPos:=trunc((CurFilePos*MainWin.JobProgress.Width)/MaxFilePos);
if CurBarPos<>LastBarPos then MainWin.JobProgress.Position:=CurBarPos;
end;
procedure TResProcessing.SetHeadersList(HeadersToProcess: THdrArray);
var i:integer;
CRRes:boolean;
begin
SetLength(HeadersList, High(HeadersToProcess));
for i:=0 to High(HeadersToProcess) do begin
HeadersList[i]:=TResHeader.Create(HeadersToProcess[i].HRDFileName,CRRes); //ЗДЕСЬ ПРОИСХОДИТ VA!!!!
if CRRes then HeadersList[i]:=HeadersToProcess[i];
end;
end;
procedure TResProcessing.ScanResFile();
var j,k,DataDone, DataOverlay, swapoffset:integer;
DataBuff: T8BitData;
LocalEntries: T16Bitdata;
a,b,ArrLength:word;
swapextens:string[4];
begin
DataOverlay:=0;
DataDone:=65536;
for j:=0 to High(HeadersList) do if Length(HeadersList[j].HeadData)>DataOverlay then DataOverLay:=Length(HeadersList[j].HeadData);
while not eof(ResFile) do begin
if High(DataBuff)<>DataDone then SetLength(DataBuff,DataDone);
BlockRead(ResFile,DataBuff[0],65536,DataDone);
for j:=0 to High(HeadersList) do begin
if HeadersList[j].SeekSelf(DataBuff,LocalEntries) then begin
SetLength(EntriesList,Length(EntriesList)+Length(LocalEntries));
for k:=0 to High(LocalEntries) do begin
EntriesList[Length(EntriesList)-Length(LocalEntries)+k].Offset:=LocalEntries[k]+FilePos(ResFile)-DataDone;
EntriesList[Length(EntriesList)-Length(LocalEntries)+k].Extension:=HeadersList[j].ResExt;
LogEvent:=HeadersList[j].ResName+" found at offset "+IntToStr(FilePos(ResFile))+".";
Synchronize(UpdateLog);
end;
end;
end;
Seek(ResFile,FilePos(ResFile)-DataOverlay);
CurFilePos:=FilePos(ResFile);
Synchronize(UpdateProgBar);
end;
ArrLength:=High(EntriesList);
for a:=ArrLength-2 downto 1 do
for b:=ArrLength-1 to ArrLength-a do
if EntriesList[b].Offset>EntriesList[b+1].Offset then begin
swapoffset:=EntriesList[b+1].Offset;
swapextens:=EntriesList[b+1].Extension;
EntriesList[b+1].Offset:=EntriesList[b].Offset;
EntriesList[b+1].Extension:=EntriesList[b].Extension;
EntriesList[b].Offset:=swapoffset;
EntriesList[b].Extension:=swapextens;
end;
end;
procedure TResProcessing.ExtractFiles();
begin
if (JobID<>RP_SCAN) and (EntriesList=nil) then exit;
end;
procedure TResProcessing.PackFiles();
begin
if (JobID<>RP_SCAN) and (EntriesList=nil) then exit;
end;
destructor TResProcessing.Destroy();
begin
CloseFile(ResFile);
HeadersList:=nil;
EntriesList:=nil;
end;
constructor TResProcessing.Create(FileName:string; HeadersToProcess: THdrArray);
begin
inherited Create(True);
ResetEngine(FileName,HeadersToProcess);
end;
procedure TResProcessing.Execute();
begin
case JobID of
RP_SCAN: ScanResFile();
RP_EXTR: ExtractFiles();
RP_PACK: PackFiles();
end;
end;
end.
← →
Ega23 © (2004-07-23 14:57) [10]1. Что такое TResHeader?
2. Чему равно HeadersToProcess[i]?
3. Может вместо того, чтобы в динамических массивах хранить объекты воспользуешься стандартным TObjectList?
← →
Sandman25 © (2004-07-23 15:03) [11]Нет inherited destroy
Нет const перед параметрами-массивами
SetLength(HeadersList, High(HeadersToProcess)+1);
или Length.
← →
Subdigger © (2004-07-23 15:06) [12]памому сдесь нада до High(HeadersToProcess)-1
for i:=0 to High(HeadersToProcess) do begin
HeadersList[i]:=TResHeader.Create(HeadersToProcess[i].HRDFileName,CRRes); //ЗДЕСЬ ПРОИСХОДИТ VA!!!!
if CRRes then HeadersList[i]:=HeadersToProcess[i];
end;
← →
Subdigger © (2004-07-23 15:09) [13]... а еще твоя фича High(HeadersToProcess) делает масив на 1 меньше єто так нада?
и почему например не так length(HeadersToProcess) или length(HeadersToProcess)-1
← →
VMcL © (2004-07-23 15:33) [14]>>DeScriptor (23.07.04 14:52) [9]
procedure TResProcessing.SetHeadersList(HeadersToProcess: THdrArray);
var i:integer;
CRRes:boolean;
begin
SetLength(HeadersList, Length(HeadersToProcess));
for i:=0 to High(HeadersToProcess) do begin
HeadersList[i]:=TResHeader.Create(HeadersToProcess[i].HRDFileName,CRRes); //ЗДЕСЬ ПРОИСХОДИТ VA!!!!
if CRRes then HeadersList[i]:=HeadersToProcess[i];
end;
end;
?
← →
DeScriptor (2004-07-23 17:38) [15]Да...... Много всего понаписали, огромное спасибо!
А в итоге правы оказались те, кто советовал юзать Length или High+1: я, как и всегда, запутался с единичкой!
Ну, почему нельзя было сделать все массивы одинаковыми?! Почему именно самые полезные - динамические, должны начинаться с 0 индекса?!.
← →
Sandman25 © (2004-07-23 17:39) [16][15] DeScriptor (23.07.04 17:38)
Все массивы начинаются с нуля :)
← →
DeScriptor (2004-07-23 21:29) [17]Разве? А если я создаю его примерно так:
MyArray: array[1...10] of byte;
Разве первым индексом не будет 1?..
← →
VML (2004-07-25 13:09) [18]>>DeScriptor (23.07.04 17:38) [15]
>Ну, почему нельзя было сделать все массивы одинаковыми?! Почему именно самые полезные - динамические, должны начинаться с 0 индекса?!.
Потому что он нуля удобнее и быстрее рассчитывать смещение в памяти от начала массива.
>>DeScriptor (23.07.04 21:29) [17]
>Разве первым индексом не будет 1?..
Формально, да.
← →
VMcL © (2004-07-25 13:10) [19]>>DeScriptor (23.07.04 17:38) [15]
>Ну, почему нельзя было сделать все массивы одинаковыми?! Почему именно самые полезные - динамические, должны начинаться с 0 индекса?!.
Потому что он нуля удобнее и быстрее рассчитывать смещение в памяти от начала массива.
>>DeScriptor (23.07.04 21:29) [17]
>Разве первым индексом не будет 1?..
Формально, да.
Страницы: 1 вся ветка
Текущий архив: 2004.08.08;
Скачать: CL | DM;
Память: 0.51 MB
Время: 0.023 c