сохранить динамический массив в файл

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

сохранить динамический массив в файл

Сообщение VirtUX » 20.05.2012 11:12:08

Есть массив, объявленый в динамике
Код: Выделить всё
type
AMas = array of Byte;

var
Mas: AMas;

во время работы проги элементы массива создаются и удаляются от 1-ого до нескольких раз. После этот массив хочу сохранить в нетипизированый файл
Код: Выделить всё
blockwrite(f, Mas[0], lenght(Mas));

Вопрос в том, - корректно-ли он сохранится? Т.е. елементы динамического массива будут гарантировано следовать друг за другом в памяти? Нет-ли в динамике скачков в адрессации?
В принципе, может-ли кто-то рассказать как выделяется адрессное пространство для динамических массивов?
Аватара пользователя
VirtUX
энтузиаст
 
Сообщения: 880
Зарегистрирован: 05.02.2008 10:52:19
Откуда: Крым, Алушта

Re: сохранить динамический массив в файл

Сообщение Maxizar » 20.05.2012 12:07:44

Т.е. елементы динамического массива будут гарантировано следовать друг за другом в памяти?

Да

При изменении размера дин массива происходит следующее:
1. Выделяется новая память (нужного размера) ; размер = запрошенный размер + (как минимум 8 байт) 4 байта для указателя ссылок и 4 байта для указания длины массива.
1.1 На 64 битных эти поля должны быть по 8 байт. Типа стандартный sizeof(int) на данной платформе.
2. Копирование старго в новый
3. Изменения указателей на новый
4. Удаление старго.


Вообще дин массив в памяти это:
[кол-во ссылок на массив(int)][длина массива(int)][данные (первый элемент массива.)(размер элемента)][второй элемент массива] и.т.д
Переменная массива указатель на первый элемент массива...

Ммм не хорошо написал, лучше так:
Пусть: sE - размер одного элемента, sE := SizeOf(элемента);
[ Адрес ][ данные ]
[ 0x0 ][ кол-во ссылок ]
[ 0x4 ][ значение High ]
[ 0x8 ][ Первый элемент массива ] <--- именно сюда указывает переменная массива.
[ 0x8+ sE ][ Второй элемент ]
[ 0x8+ 2*sE ][ Третий элемент ]


Более подробно можно прочитать скажем тут: Работа с указателями (очень советую, хорошая статья)
Там есть раздел про дин массивы.

PS. Отличие дин массивов в Free Pascal от Delphi, в том, что FPC хранит не значение Length, а значение High (High = Length -1), это необходимо знать, если будете передовать указатель на массив в процедуру на другом языке или работать на уровне ассемблера.
PS. #2 Почему blockwrite ? а не просто запись в файл (Write), потом вроде у blockwrite ограничение на 64 КБ....
Maxizar
постоялец
 
Сообщения: 385
Зарегистрирован: 20.03.2010 19:48:14

Re: сохранить динамический массив в файл

Сообщение VirtUX » 20.05.2012 12:32:18

Maxizar писал(а):Почему blockwrite ? а не просто запись в файл (Write), потом вроде у blockwrite ограничение на 64 КБ

BlockWrite - т.к. кроме этого массива в файл сохраняются еще другие массивы, различные переменные и т.д. Грубо говоря у меня записывается БД, с моим уникальным форматом заголовков и размещения данных. Максимальный размер записи не превышает 16Кб. Т.ч. BlockWrite - устраивает во всех отношениях.
P.S. Спасибо за консультацию :)
Аватара пользователя
VirtUX
энтузиаст
 
Сообщения: 880
Зарегистрирован: 05.02.2008 10:52:19
Откуда: Крым, Алушта

Re: сохранить динамический массив в файл

Сообщение Сквозняк » 22.05.2012 10:00:21

blockwrite(f, Mas[0], lenght(Mas));

Вопрос в том, - корректно-ли он сохранится? Т.е. елементы динамического массива будут гарантировано следовать друг за другом в памяти? Нет-ли в динамике скачков в адрессации?

Грубо говоря у меня записывается БД, с моим уникальным форматом заголовков и размещения данных. Максимальный размер записи не превышает 16Кб.

У меня аналогичная "БД" в виде текстового файла с заголовками и следующими за ним десятичными цифрами через запятую. Динамический массив это почти тоже самое что и ansistring, при чтении из файла в такие массивовы данных одним куском возникает одинаковый фатальный баг, по крайней мере в линуксе - разрывы там есть. А для сохранения данных в файл можешь использовать функцию которая на входе принимает массив нужного тебе типа а на выходе возвращает обычный массив фиксированной длины типа byte, тогда разрывов гарантированно не будет.
Сквозняк
энтузиаст
 
Сообщения: 1129
Зарегистрирован: 29.06.2006 22:08:32

Re: сохранить динамический массив в файл

Сообщение SAK » 22.05.2012 21:54:58

Сквозняк писал(а):при чтении из файла в такие массивовы данных одним куском возникает одинаковый фатальный баг, по крайней мере в линуксе - разрывы там есть.

Приведите пример кода доказывающий это утверждение.
SAK
постоялец
 
Сообщения: 158
Зарегистрирован: 18.02.2006 00:45:14
Откуда: Тим

Re: сохранить динамический массив в файл

Сообщение Сквозняк » 23.05.2012 01:13:49

SAK писал(а):Приведите пример кода доказывающий это утверждение.

Пожалуйста, если не верите, но красоту кода наводить не буду - пример должен обкатать систему во всех нужных режимах.
Код: Выделить всё
{$GOTO ON}
{$MODE FPC}
{$R+}

uses

BASEUNIX, UNIX;

CONST
LIMIT=10000000;

var
Q2,W2: LONGINT;
QQ3: ARRAY OF BYTE;
//QQ3: ARRAY[1..100000] OF BYTE;
IMJA_FAILA: ANSISTRING;

label
100;


begin
IMJA_FAILA:='massiv.pp';
Q2:=FPOPEN(IMJA_FAILA,Open_RDONLY);
IF Q2<0 THEN GOTO 100;
W2:=FPLSEEK(Q2,0,SEEK_END);
WRITELN('DLINA FAILA = ',W2);
FPLSEEK(Q2,0,SEEK_SET);
IF W2>LIMIT THEN W2:=LIMIT;
IF W2<1 THEN GOTO 100;
SETLENGTH(QQ3,W2+200);
WRITELN('PROVERKA 1');
FPREAD(Q2,QQ3,W2);
WRITELN('PROVERKA 2');


100:
FPCLOSE(Q2);
end.

Компилятор 2.44, из-за лазаруса не использую новый - не хочу ломать совместимость ради не очень нужных на данный момент патчей.
Сквозняк
энтузиаст
 
Сообщения: 1129
Зарегистрирован: 29.06.2006 22:08:32

Re: сохранить динамический массив в файл

Сообщение SAK » 24.05.2012 11:52:01

Не надо винить компилятор в собственных ошибках.
FPREAD(Q2, QQ3[0], W2);
SAK
постоялец
 
Сообщения: 158
Зарегистрирован: 18.02.2006 00:45:14
Откуда: Тим

Re: сохранить динамический массив в файл

Сообщение Сквозняк » 25.05.2012 01:02:25

В статических массивах и строках индекс указывать не нужно, зачем же этот трюк применяется в динамических?
Сквозняк
энтузиаст
 
Сообщения: 1129
Зарегистрирован: 29.06.2006 22:08:32

Re: сохранить динамический массив в файл

Сообщение SSerge » 25.05.2012 13:11:54

Сквозняк писал(а):В статических массивах и строках индекс указывать не нужно, зачем же этот трюк применяется в динамических?


Подозреваю, что дело здесь совершенно не в массивах, а в том, на что показывает _адрес_ переменной. В случае стандартного массива - это его первый реальный элемент, в случае с динамическим - видимо, структура данных, которую описал уважаемый Maxizar в посте выше
SSerge
энтузиаст
 
Сообщения: 971
Зарегистрирован: 12.01.2012 05:34:14
Откуда: Барнаул

Re: сохранить динамический массив в файл

Сообщение Сквозняк » 25.05.2012 21:27:36

С такими различиями при смене типа строки или массива необходимо проверять все случаи использования их при записи и чтении файлов, хорошее развлечение придумано.
Сквозняк
энтузиаст
 
Сообщения: 1129
Зарегистрирован: 29.06.2006 22:08:32

Re: сохранить динамический массив в файл

Сообщение SAK » 26.05.2012 23:18:23

SSerge писал(а):В случае стандартного массива - это его первый реальный элемент, в случае с динамическим - видимо, структура данных, которую описал уважаемый Maxizar в посте выше

Нет, в случае динамического массива переменная представляет собой указатель на первый элемент массива. Попробуйте запросить SizeOf(QQ3). В приведённом примере в функцию FPREAD передаётся адрес указанной переменной, но в случае статического массива это адрес самого массива, а в случае динамического - адрес указателя на массив. Когда указываем индекс, то в любом случае передаётся адрес указанного элемента массива.
SAK
постоялец
 
Сообщения: 158
Зарегистрирован: 18.02.2006 00:45:14
Откуда: Тим

Re: сохранить динамический массив в файл

Сообщение Maxizar » 27.05.2012 13:27:04

использовать прямое преобразование тобишь как то так:
Код: Выделить всё
Ptr := @DynArray[0]


Тогда как при использовании встроенного ассемблера вам развязывает все руки. Можете передать массив как переменную и дальше все что душе угодно..
В исходниках прилогаю пример, как на асме прочитать длину массива, кол-во ссылок, значение адреса первого элемента.

PS. Массивы всегда непрерывны, ВСЕГДА. элемент n лежит после элемента n-1, и перед n+1. Каждый элемент занимает ровно SizeOf(n)
PS. Как меняются адреса элементов в массиве в зависимости от размера элемента см в исходнике....
PS. Если в памяти нет свободного участка памяти такого большого размера, в случае динамического массива смотри как работает функция SetLength.
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Последний раз редактировалось Maxizar 27.05.2012 18:05:42, всего редактировалось 2 раз(а).
Maxizar
постоялец
 
Сообщения: 385
Зарегистрирован: 20.03.2010 19:48:14

Re: сохранить динамический массив в файл

Сообщение zub » 27.05.2012 14:46:14

>>2. Переменная статического массива и динамического массива указывают на первый элемент массива. Тоесть они являются указателями. Всегда.
Переменная динамического массива как и стринг - по сути являются указателем на данные, статический массив это просто сами данные
отсюда и
>>4.Передать переменную динамического массива как указатель нельзя... Да он явл-ся указателем на первый элемент массива,
>>НО передать и использовать его как указатель нельзя. Это Защита не опытных программистов, наверное, либо стандарт.
можно ее передать как указатель, но указатель этот будет не на первый элемент, а на саму переменную, отсюда и выкрутасы в виде:
Ptr := @DynArray[0];
Ptr := ppointer(@DynArray)^;

т.е. в случае статического массива
@StatArray - адрес первого элемента массива
в случае динамического
@DynArray - адрес переменной DynArray, в которой содержится адрес первого элемента
edit: поправил, с первого раза написал ерунду))
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

Re: сохранить динамический массив в файл

Сообщение SAK » 27.05.2012 15:40:32

Maxizar писал(а):2. Переменная статического массива и динамического массива указывают на первый элемент массива. Тоесть они являются указателями. Всегда.

Это как? Например возьмём статический массив var m: array[1..250]of word;
Вы хотите сказать, что переменная m является указателем? Если это указатель, то размер этой переменной должен быть равен размеру указателя: SizeOf(m)=SizeOf(Pointer)? На самом деле SizeOf(m)=500.

Maxizar писал(а):3. Переменную Статического массива можно передавать и использовать как указатель.

Приведите пример. Я не могу представить как это сделать.

zub писал(а):Ptr := @DynArray[0];

Добавлю: при такой записи Ptr всегда будет указывать на первый элемент любого массива как динамического, так и статического.
SAK
постоялец
 
Сообщения: 158
Зарегистрирован: 18.02.2006 00:45:14
Откуда: Тим

Re: сохранить динамический массив в файл

Сообщение Maxizar » 27.05.2012 18:03:30

Приношу извинения... Давно не писал на Паскале... (порядка 1.5 лет) Да написал чушь...... Следствия привыкания к языку Си... там это как два пальца..
Maxizar
постоялец
 
Сообщения: 385
Зарегистрирован: 20.03.2010 19:48:14

След.

Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex [Bot] и гости: 1

Рейтинг@Mail.ru