Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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.006 c
1-12821
AlexKost
2003-04-22 15:38
2003.05.05
Загрузка функции из пакета


7-12958
crushfm
2003-03-14 09:56
2003.05.05
Харддиск


14-12895
Вольный Стрелок
2003-04-16 11:36
2003.05.05
отследить позицию мыши


1-12804
новый
2003-04-22 14:36
2003.05.05
Как в Pascal сделать чтобы ф-ция возвращала массив?


3-12617
SiJack
2003-04-15 14:26
2003.05.05
Как создать запрос SQL?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский