Форум: "Основная";
Текущий архив: 2003.05.05;
Скачать: [xml.tar.bz2];
ВнизКопия динамического массива Найти похожие ветки
← →
Zergling (2003-04-23 06:26) [0]День добрый уважаемые! Совершенно вылетело из бошки, как правильно скопировать динамические массивы, т.е. один мссив приравнять к другому.Подскажите пожадуйста!
var
OpisMon, OpisSop: Array of TOpis;
Procedure LoadOpis(FileName: TFileName; Section: TSection);
var
FileOpis: File;
RecOpis: TOpis;
I, BytesRead: Integer;
TmpArrayOpis: Array of TOpis;
begin
if not FileExists(FileName) then EXIT;
AssignFile(FileOpis, FileName);
try
FileMode := 0;
Reset(FileOpis, 1);
SetLength(TmpArrayOpis, FileSize(FileOpis) div SizeOf(TOpis));
for I := Low(TmpArrayOpis) to High(TmpArrayOpis) do
begin
BlockRead(FileOpis, RecOpis, SizeOf(RecOpis), BytesRead);
if BytesRead <> SizeOf(RecOpis) then raise Exception.Create("Ошибка чтения файла -> " + FileName);
TmpArrayOpis[I] := RecOpis;
end;
case Section of
// Ругется здесь
Monomer: OpisMon := Copy(TmpArrayOpis, Low(TmpArrayOpis), High(TmpArrayOpis));
// А такой метод если память не изменяет: OpisSop получает ссылку на TmpArrayOpis
Sopolimer: OpisSop := TmpArrayOpis;
end;
finally
CloseFile(FileOpis);
end;
end;
← →
Separator (2003-04-23 06:56) [1]Dest:= Copy(Source, Index, Count)
← →
Separator (2003-04-23 07:01) [2]
type
TArrOpis = array of TOpis;
...
var
OpisMon, OpisSop: TArrOpis;
...
var
TmpArrayOpis: TArrOpis;
...
OpisMon := Copy(TmpArrayOpis, Low(TmpArrayOpis), High(TmpArrayOpis) - Low(TmpArrayOpis) + 1)
← →
evvcom (2003-04-23 08:30) [3]Вроде код процедуры полностью приведен, если не считать, что не хватает нескольких предварительных объявлений (TOpis, Section и др.), поэтому предполагаю, что ничего криминального там нет.
А криминал есть вот где. Типы переменных OpisMon, OpisSop: Array of TOpis; и TmpArrayOpis: Array of TOpis; - это совершенно разные типы с точки зрения компилятора, хотя и имеют одинаковую структуру. Воспользуйтесь вариантом, предложенным Separator.
Кроме того для оптимизации кода я сделал бы немного не так. В приведенном коде не видно смысла в использовании цикла для чтения массива. Можно сделать проще:
fSize := FileSize(FileOpis);
if fSize mod SizeOf(TOpis) <> 0 then
raise Exception.Create("Ошибка чтения файла -> " + FileName);
SetLength(TmpArrayOpis, fSize div SizeOf(TOpis));
BlockRead(FileOpis, TmpArrayOpis[0], fSize, BytesRead);
И еще одно очень слабое место:
Sopolimer: OpisSop := TmpArrayOpis;
Если и мне память не изменяет, и OpisSop получает ссылку на TmpArrayOpis, то при выходе из процедуры код, сгенеренный компилятором, уничтожает переменную TmpArrayOpis, а вместе с ней и все ее данные. И последующее обращение к глобальной OpisSop вызовет Access Violation
← →
Skier (2003-04-23 08:46) [4]>Zergling
Move(...) ?
← →
evvcom (2003-04-23 08:54) [5]Согласен со Skier.
И еще, я хоть и написал "предполагаю, что ничего криминального там нет." (в смысле в структуре TOpis), а теперь начинаю сомневаться. Если в ней имеются данные типа string, то это уже криминал при таком способе загрузке данных.
← →
Zergling (2003-04-23 09:04) [6]Вариант предложенный Separator © полоностью работоспособен. Большое спасибо за ответы на данный вопрос!
← →
REA (2003-04-23 09:10) [7]>уничтожает переменную TmpArrayOpis, а вместе с ней и все ее данные.
Не уверен. Не исключено и более того вероятно, что компилятор как и со строками держит счетчик ссылок на динамические массивы, а потому освободит память только при уничтожении и второго массива.
← →
Zergling (2003-04-23 09:27) [8]evvcom © (23.04.03 08:30)
Если ты еще забегаещь на эту ветку, то вопрос к тебе:
fSize := FileSize(FileOpis);
BlockRead(FileOpis, TmpArrayOpis[0], fSize, BytesRead);
BlockRead считывает данные из файла блоком размером fSize, а как это будет сказываться на ОЗУ моей мшины, если файл состовляет несколько мегабайт. По этому вопросу я не вкурсе, просветите кто знает по потробнее пожалуйста.
← →
evvcom (2003-04-23 09:46) [9]> REA
У меня был что-то типа этого случай, хотя утверждать, что он идентичен, не могу. Выяснение подобных проблем зачастую приходится вести через CPU Window, так вот мой TempArray был начисто уничтожен вместе со всеми стрингами, в него входящими.
← →
Zergling (2003-04-23 09:53) [10]Zergling (23.04.03 09:27)
А фигню наверно спросил, заполненный массив будет жрать столькоже пмяти, сколько и считываемый блок из файла.
← →
evvcom (2003-04-23 10:13) [11]> Zergling
А в цикле ты читаешь не весь файл? Это сужу по приведенному коду. В Win32 память устроена линейно-виртуально, т.е. ты можешь не заботиться (ну практически с довольно небольшими объемами) об этом. Теоретически твоему процессу выделяется 4 ГБ памяти, но практически даже с учетом файла подкачки значительно меньше, все зависит от объема оперативки, но все равно довольно много. И несколько мегабайт (10, 20, 30) - это вполне нормально. Даже при изменении размера массива, например, с 1 до 2 МБ, если за этим 1 МБ располагаются еще какие-то данные, и массив не может быть просто так расширен, выделяются 2 МБ в другом месте памяти, туда копируются прежние 1 МБ из массива, и прежний 1 МБ освобождаются. По-моему это все так, когда-то разбирался, уже не помню когда, во всяком случае, я этого всегда придерживаюсь, и такие понятия меня пока не подводили.
← →
Separator (2003-04-23 10:21) [12]
> evvcom © (23.04.03 08:30)
> И еще одно очень слабое место:
> Sopolimer: OpisSop := TmpArrayOpis;
> Если и мне память не изменяет, и OpisSop получает ссылку
> на TmpArrayOpis, то при выходе из процедуры код, сгенеренный
> компилятором, уничтожает переменную TmpArrayOpis, а вместе
> с ней и все ее данные. И последующее обращение к глобальной
> OpisSop вызовет Access Violation
В данном случае OpisSop не получит ччылку на TmpArrayOpis, а произойдёт полное копирование данных из массива TmpArrayOpis в массив OpisSop, но при условии, что(Length(OpisSop) >= TmpArrayOpis) or (OpisSop = nil)
← →
evvcom (2003-04-23 10:28) [13]> Separator
Не буду спорить. Поэтому я и написал "Если ..., и OpisSop получает ссылку на TmpArrayOpis", потому как не уверен. В таких случаях, где не уверен, так как сколько не практикуйся, а всех тонкостей все равно не узнаешь, я всегда ставлю bp на этом месте с дальнейшим CPU Window и несколько шагов трассировки, чтобы быть уверенным в подобных нюансах.
← →
Separator (2003-04-23 10:34) [14]
> evvcom © (23.04.03 10:28)
Я сам в этом не был уверен, но открыл Help от Архангельского и там про всё это было написано, потом посмотрел, что пишут в Help от Borland, там окозалось почти тоже самое, так что у меня не осталось сомнений.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2003.05.05;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.007 c