Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Подводные камни
  
О разделе

Список по категориям
Общий список

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  08:09[Войти] | [Зарегистрироваться]

VCL.List index out of bounds при корректном значении индекса

Антон Григорьев
дата публикации 16-08-2004 13:36

КАТЕГОРИЯБИБЛИОТЕКА.VCL.List index out of bounds при корректном значении индекса
ПРОДУКТDelphi
ПЛАТФОРМАWindows


Windows позволяет с каждой строкой списка ListBox’а или ComboBox’а связать либо число, либо указатель (точнее – некоторую четырёхбайтную величину, которую программа может трактовать как число, как указатель или как что-либо ещё). В VCL эта возможность используется для привязки к строкам списка объектов – четырёхбайтная величина по умолчанию трактуется как TObject. Доступ к этим объектам осуществляется через свойства TComboBox.Items.Objects[Index] и TListBox.Items.Objects[Index].

Иногда всё-таки требуется привязывать к строкам не объекты, а числа. Для этого можно воспользоваться явным приведением типов, например:

ComboBox1.Items.Objects[I] := TObject(17);
I := Integer(ComboBox1.Items.Objects[I]);

Если таким образом связать со строкой значение –1, то при попытке получить это значение возникнет исключение EStringListError с комментарием "List index out of bounds". Рассмотрим следующий пример:

ComboBox1.Items.Clear;
ComboBox1.Items.AddObject(‘Text’,TObject(-1));
I := Integer(ComboBox1.Items.Object[0]);             {*}
Исключение возникнет при попытке выполнить строку, отмеченную звёздочкой, хотя очевидно, что индекс в данном случае корректен.

Чтобы понять причину ошибки, необходимо рассмотреть, как осуществляется чтение значения, привязанного к строке, на уровне Windows API. Рассмотрим это на примере ComboBox’а. Для получения значения необходимо послать ComboBox’у сообщение CB_GetItemData. Результатом обработки этого сообщения будет значение, связанное с указанной строкой, или CB_Err, если при обработке сообщения возникнет ошибка. При этом документация не уточняет, какие именно ошибки могут в принципе возникнуть и как узнать, какая именно ошибка произошла.

Метод TComboBoxStrings.GetObject, через который читается значение свойства Objects, интерпретирует получение CB_Err однозначно: генерирует EStringListError с комментарием "List index out of bounds".

Проблема заключается в том, что численное значение константы CB_Err = –1. Поэтому и в случае ошибки, и в случае, когда строке сопоставлено значение –1, CB_GetItemData вернёт одинаковый результат. И метод TComboBoxStrings.GetObject интерпретирует этот результат как ошибку. (А что ему ещё остаётся делать?)

Аналогичная проблема по тем же причинам возникает и при использовании ListBox’а. Проблема является прямым следствием документированных особенностей работы Windows и модели работы VCL, поэтому встречается во всех версиях Windows и во всех версиях Delphi. Эта же проблема возникает при попытки использования значения 4294967295, т.к. на двоичном уровне это число записывается той же комбинацией бит, что и –1.

При использовании свойства Objects по прямому назначению, т.е. для хранения объектов, эта проблема не может возникнуть, потому что $FFFFFFFF – это адрес самого старшего байта в четырёхгигабайтном виртуальном адресном пространстве программы. Эта область адресного пространства зарезервирована системой, и менеджер памяти Delphi не может выделить память для объекта в этой области.


Типовые решения


Рекомендуемые способы решения проблемы:
  1. Пересмотреть алгоритм и отказаться от связывания значения –1 со строками.
  2. Напрямую посылать CB_GetItemData ComboBox’у, а попадание индекса в диапазон контролировать самостоятельно другими методами.



Смотрите также материалы по темам:
[TListBox] [TComboBox] [Ядро, структуры и механизмы Windows, использование API] [Отображение списков, сеток]

 Обсуждение материала [ 19-08-2004 13:59 ] 2 сообщения
  
Время на сайте: GMT минус 5 часов

Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
Функция может не работать в некоторых версиях броузеров.

Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

 
© При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
Все используемые на сайте торговые марки являются собственностью их производителей.

Яндекс цитирования