Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 2 700

/ вопрос решён /

Здравствуйте, эксперты!
Проблема такова. Имеется код (часть его в приложении). Функция определяет имеющиеся накопители и информацию о них. При выполнении программы выдается ошибка. Для верности сделала скрин. Посмотрите, пожалуйста. Я днями-ночами сижу над этим, может, уже просто очевидного не замечаю.
Заранее благодарю.

К вопросу прикреплён файл. Загрузить » (срок хранения: 60 дней с момента отправки вопроса)

Приложение:
  1.  
  2.  
  3. type
  4. TDriveRec = packed record
  5. Name: String;
  6. DrType: String;
  7. Sectors: DWord;
  8. Bytes: DWord;
  9. FreeClust: DWord;
  10. TotalClust: DWord;
  11. FreeSpace: Int64;
  12. TotalSpace: Int64;
  13. end;
  14.  
  15. type TDrives = Array of TDriveRec;
  16.  
  17.  
  18. //.....................
  19.  
  20.  
  21. function GetDrives (var Drive: TDrives; var count: byte): boolean;
  22.  
  23. const
  24. DriveTypes: array[0..6] of String = ('Unknown', 'Error disk name', 'FDD', 'HDD',
  25. 'Remote', 'CD-ROM', 'RAM-DISK');
  26. var
  27. Drives_: DWord;
  28. dType: UINT;
  29. i: byte;
  30. Dr: Char;
  31. SectorsPerCluster: DWord;
  32. BytesPerSector: DWord;
  33. NumFreeClusters: DWord;
  34. TotalClusters: DWord;
  35. FreeSpace: Int64;
  36. TotalSpace: Int64;
  37. begin
  38. count:=1;
  39. Drives_ := GetLogicalDrives;
  40. for i := 0 to 25 do
  41. if Boolean(Drives_ and (1 shl i)) then
  42. begin
  43. Dr := Chr(i + $41);
  44.  
  45. dType := GetDriveType(PChar(Dr + ':'));
  46. Drive[count].DrType:= DriveTypes[dType];
  47. GetDiskFreeSpace(PChar(Dr + ':'), SectorsPerCluster, BytesPerSector, NumFreeClusters, TotalClusters);
  48. FreeSpace:=DiskFree(Integer(Dr));
  49. TotalSpace:=DiskSize(Integer(Dr));
  50. Drive[count].Sectors:= SectorsPerCluster;
  51. Drive[count].Bytes:= BytesPerSector;
  52. Drive[count].FreeClust:= NumFreeClusters;
  53. Drive[count].TotalClust:= TotalClusters;
  54. Drive[count].FreeSpace:= FreeSpace;
  55. Drive[count].TotalSpace:= TotalSpace;
  56. Inc(count);
  57. end
  58. end;
  59.  
  60.  
  61.  
  62.  
  63.  
  64. var
  65.  
  66. Drive: TDrives;
  67. count: byte;
  68. // ............
  69.  
  70. begin
  71.  
  72. // .......
  73.  
  74. GetDrives(Drive, count);
  75.  
  76. // .......
  77.  
  78. end;


Insomnia Вопрос решён, но можно продолжить его обсуждение в мини-форуме

Вопрос задала: 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).

У вас скорее всего нужно вставить это тут:

Приложение:
  1. //......
  2. if Boolean(Drives_ and (1 shl i)) then
  3. begin
  4. SetLength(Drive,count);
  5. //......


Ответ отправил: Amidamaru (статус: 4-ый класс)
Время отправки: 29 апреля 2009, 09:42
Оценка за ответ: 5


Мини-форум вопроса

Всего сообщений: 4; последнее сообщение — 29 апреля 2009, 18:11; участников в обсуждении: 3.
Amidamaru

Amidamaru (статус: 4-ый класс), 29 апреля 2009, 09:44 [#1]:

Забыл дописать. После окончания ипользования динамического массива нужно освободить занимаемую им память:

SetLength(Drive,0);

И ещё одно, индексы в динамичемских массивах начинаются с 0. Т.е. Drive[0] - первый элемент. Поэтому используйте Drive[count-1]
Приглашаю Вас на наш IRC-канал: #delphiintru в сети DalNet.
Вадим К

Вадим К (статус: Академик), 29 апреля 2009, 10:18 [#2]:

Дополняю свой ответ.
Индексы.. либо используйте count:=0; вместо count:=1; , либо придется заменить все [count] на [count-1]
В моем ответе я выделяю "заведомо достаточное место" - дисков может быть больше 26 в системе, но не букв дисков.
Amidamaru предлагает довыделять память по мере надобности. Вызывать функцию SetLength при малых размерах массива достаточно не ресурсоемко. Но вот уже при 10-20 начинает сказываться.
Это для нас код Setlengt(a, length(a)+1) - довыделить места на один элемент выглядит просто, а делфи генерирует весьма большой код. Где то так
//выделить место под новый массив
//скопировать в него старый
//удалить старый.
Понятно, что это можно оптимизировать (и оно оптимизируется) - например выделятся сразу пачками по 16 элементов. Но...
Галочка "подтверждения прочтения" - вселенское зло.
Amidamaru

Amidamaru (статус: 4-ый класс), 29 апреля 2009, 10:29 [#3]:

Да, можно оптимизировать. Выделить память сразу под весь массив, а в конце процедуры GetDrivers вставить строчку SetLength(Drive,count);
Приглашаю Вас на наш IRC-канал: #delphiintru в сети DalNet.
Insomnia

Insomnia (статус: Посетитель), 29 апреля 2009, 18:11 [#4]:

Спасибо, ребята! Все исправила, все работает :)

31 января 2011, 19:36: Статус вопроса изменён на решённый (изменил модератор Ерёмин А.А.): Автоматическая обработка (2 и более ответов с оценкой 5)

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 6 апреля 2020, 23:57
Выполнено за 0.02 сек.
Рейтинг@Mail.ru