|
Вопрос # 2 700/ вопрос решён / |
|
Здравствуйте, эксперты!
Проблема такова. Имеется код (часть его в приложении). Функция определяет имеющиеся накопители и информацию о них. При выполнении программы выдается ошибка. Для верности сделала скрин. Посмотрите, пожалуйста. Я днями-ночами сижу над этим, может, уже просто очевидного не замечаю.
Заранее благодарю.
К вопросу прикреплён файл. Загрузить » (срок хранения: 60 дней с момента отправки вопроса)
Приложение: Переключить в обычный режим-
-
- type
- TDriveRec = packed record
- Name: String;
- DrType: String;
- Sectors: DWord;
- Bytes: DWord;
- FreeClust: DWord;
- TotalClust: DWord;
- FreeSpace: Int64;
- TotalSpace: Int64;
- end;
-
- type TDrives = Array of TDriveRec;
-
-
- //.....................
-
-
- function GetDrives (var Drive: TDrives; var count: byte): boolean;
-
- const
- DriveTypes: array[0..6] of String = ('Unknown', 'Error disk name', 'FDD', 'HDD',
- 'Remote', 'CD-ROM', 'RAM-DISK');
- var
- Drives_: DWord;
- dType: UINT;
- i: byte;
- Dr: Char;
- SectorsPerCluster: DWord;
- BytesPerSector: DWord;
- NumFreeClusters: DWord;
- TotalClusters: DWord;
- FreeSpace: Int64;
- TotalSpace: Int64;
- begin
- count:=1;
- Drives_ := GetLogicalDrives;
- for i := 0 to 25 do
- if Boolean(Drives_ and (1 shl i)) then
- begin
- Dr := Chr(i + $41);
-
- dType := GetDriveType(PChar(Dr + ':'));
- Drive[count].DrType:= DriveTypes[dType];
- GetDiskFreeSpace(PChar(Dr + ':'), SectorsPerCluster, BytesPerSector, NumFreeClusters,
TotalClusters);
- FreeSpace:=DiskFree(Integer(Dr));
- TotalSpace:=DiskSize(Integer(Dr));
- Drive[count].Sectors:= SectorsPerCluster;
- Drive[count].Bytes:= BytesPerSector;
- Drive[count].FreeClust:= NumFreeClusters;
- Drive[count].TotalClust:= TotalClusters;
- Drive[count].FreeSpace:= FreeSpace;
- Drive[count].TotalSpace:= TotalSpace;
- Inc(count);
- end
- end;
-
-
-
-
-
- var
-
- Drive: TDrives;
- count: byte;
- // ............
-
- begin
-
- // .......
-
- GetDrives(Drive, count);
-
- // .......
-
- end;
 |
Вопрос задала: Insomnia (статус: Посетитель)
Вопрос отправлен: 29 апреля 2009, 08:48
Состояние вопроса: решён, ответов: 2.
|
Ответ #1. Отвечает эксперт: Вадим К
Здравствуйте, Insomnia!
Типичная проблема - массив объявлен, а место под него не выделено. В данном случае "виноват" массив Drive. Исправить можно двумя способами.
а)
переписать объявление массива так
type TDrives = Array[0..25] of TDriveRec;
или явно выделить место под массив - над строкой GetDrives(Drive, count); дописать строку SetLength(Drive, 26);
 |
Ответ отправил: Вадим К (статус: Академик)
Время отправки: 29 апреля 2009, 09:42
Оценка за ответ: 5
|
Ответ #2. Отвечает эксперт: Amidamaru
Здравствуйте, Insomnia!
Конечно будет ошибка выскакивать. У вас же Drive это динамический массив, значит прежде чем его использовать, нужно задать ему длинну. Например SetLength(Drive,26).
У вас скорее всего нужно вставить это тут:
 |
Ответ отправил: Amidamaru (статус: 4-ый класс)
Время отправки: 29 апреля 2009, 09:42
Оценка за ответ: 5
|
Мини-форум вопроса
Всего сообщений: 4; последнее сообщение — 29 апреля 2009, 18:11; участников в обсуждении: 3.
|
Amidamaru (статус: 4-ый класс), 29 апреля 2009, 09:44 [#1]:
Забыл дописать. После окончания ипользования динамического массива нужно освободить занимаемую им память:
SetLength(Drive,0);
И ещё одно, индексы в динамичемских массивах начинаются с 0. Т.е. Drive[0] - первый элемент. Поэтому используйте Drive[count-1]
|
|
Вадим К (статус: Академик), 29 апреля 2009, 10:18 [#2]:
Дополняю свой ответ.
Индексы.. либо используйте count:=0; вместо count:=1; , либо придется заменить все [count] на [count-1]
В моем ответе я выделяю "заведомо достаточное место" - дисков может быть больше 26 в системе, но не букв дисков.
Amidamaru предлагает довыделять память по мере надобности. Вызывать функцию SetLength при малых размерах массива достаточно не ресурсоемко. Но вот уже при 10-20 начинает сказываться.
Это для нас код Setlengt(a, length(a)+1) - довыделить места на один элемент выглядит просто, а делфи генерирует весьма большой код. Где то так
//выделить место под новый массив
//скопировать в него старый
//удалить старый.
Понятно, что это можно оптимизировать (и оно оптимизируется) - например выделятся сразу пачками по 16 элементов. Но...
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Amidamaru (статус: 4-ый класс), 29 апреля 2009, 10:29 [#3]:
Да, можно оптимизировать. Выделить память сразу под весь массив, а в конце процедуры GetDrivers вставить строчку SetLength(Drive,count);
|
|
Insomnia (статус: Посетитель), 29 апреля 2009, 18:11 [#4]:
Спасибо, ребята! Все исправила, все работает
|
31 января 2011, 19:36: Статус вопроса изменён на решённый (изменил модератор Ерёмин А.А.): Автоматическая обработка (2 и более ответов с оценкой 5)
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|