| 
| 
 | Вопрос # 6 499/ вопрос решён / | 
 |  Здравствуйте, эксперты!у меня непонятная проблема. Пытаюсь запустить программу пошагово, и отладчик сразу показывает CPU Window. Я много чего перепробовал уже и пришёл к выводу, что это ошибка в коде. Но компилятор её не видит. Прочитав статью многоуважаемого GunSmoker (http://www.gunsmoker.ru/2012/02/5.html), я заметил такую особенность: напротив всех мест машинного кода, которые соответствуют исходному вроде бы можно поставить BP, однако у меня в программе в некоторых местах это нельзя сделать даже на точке входа в метод. Почему?
 К вопросу прикреплён файл. Загрузить » (срок хранения: 60 дней с момента отправки вопроса) Примечание #1 (11 декабря 2013, 16:29): Все возможные мануалы по поводу настройки отладчика и переключения Debug/Release режимов я перечитал несколько раз. Примечание #2 (12 декабря 2013, 17:48): Добавлю, что структура юнитов такая: есть юнит с обобщённым классом [TGenericCollection<T> = class(TCollection)], от него наследуются другие коллекции в проекте, каждая находится в своём отдельном юните. Это одно из моих подозрений, но оно не первостепенное.
 Вчера на тестовом проекте я обнаружил такую особенность: есть два юнита "модели" и один юнит "формы" (схема модель-контрлллер-представление). Юнит с классом-родителем подключается к юниту формы в интерфейсной части, а юнит с классом-наследником - к части реализации. К юниту с классом-родителем юнит формы подключается в разделе реализации. И вот тут появляется окно ЦПУ. Причём первые два запуска - нормально, отладчик. На третий - окно ЦПУ. Как только я убираю юнит класса-наследника из реализации юнита формы - всегда отладчик стартует нормально. Ещё влияет максимальный размер стека в свойствах проекта. Не знаю, как, но отладчик перед "падением" запускается большее число раз, если его увеличить. А вот на втором проекте - большом - отладчик падает сразу. И в конце концов среда выдаёт "разрушительный сбой" в dcc140.dll
 
 [DCC Fatal Error] Exception EAccessViolation: Access violation at address 09755F99 in module 'dcc140.dll'. Write of address 00000003
 
 [DCC Error] Разрушительный сбой (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))
 Примечание #3 (13 декабря 2013, 16:10): Я решил вопрос сам.Итак, пишу для тех, кто может с этим столкнуться.
 Я переопределял класс коллекции и сделал его, как написано выше, обобщённым. Поглядев на класс TCollection, я скопировал оттуда Enumerator. Вот его код:
 
 TCollectionEnumerator = class
 private
 FIndex: Integer;
 FCollection: TCollection;
 public
 constructor Create(ACollection: TCollection);
 function GetCurrent: TCollectionItem; inline;
 function MoveNext: Boolean;
 property Current: TCollectionItem read GetCurrent;
 end;
 
 И я сделал ТОЧНО такой же себе, с учётом необходимых изменений. В этом и была моя ошибка. Вот его код:
 
 TGCEnumerator<TGI: TGenericItem> = class
 strict private
 FIndex: Integer;
 FGC: TGenericCollection<TGI>;
 
 public
 constructor Create(AGC: TGenericCollection<TGI>);
 destructor Destroy; override;
 
 function GetCurrent: TGI; inline;
 function MoveNext: Boolean;
 
 property Current: TGI read GetCurrent;
 end;
 
 И вот тут кроется злостный и гадкий жук. В чём там дело, я не знаю, да это и не важно. Просто так работает компилятор, и всё. А именно: виновата директива inline. Так как класс у меня обощённый, то инлайн ломает какие-то инструкции, что и рушило отладчик, который показывал ЦПУ вместо нормальной пошаговости. Как только я убрал эту директиву - всё заработало отлично. Обращаю ваше внимание, что коллекция по прежнему остаётся обощённой. Не обобщён только энумератор, который я перенёс внутрь класса коллекции.
 
 Код, который был:
 
 TGCEnumerator<TGI: TGenericItem> = class;
 
 TGenericCollection<TGI: TGenericItem> = class(TOwnedCollection)
 ...
 public
 function GetEnumerator: TGCEnumerator<TGI>;
 ...
 end;
 
 TGCEnumerator<TGI: TGenericItem> = class
 strict private
 FIndex: Integer;
 FGC: TGenericCollection<TGI>;
 
 public
 constructor Create(AGC: TGenericCollection<TGI>);
 destructor Destroy; override;
 
 function GetCurrent: TGI; inline;
 function MoveNext: Boolean;
 
 property Current: TGI read GetCurrent;
 end;
 
 Код, который стал:
 
 TGenericCollection<TGI: TGenericItem> = class(TOwnedCollection)
 type
 TGCEnumerator = class
 strict private
 FIndex: Integer;
 FGC: TGenericCollection<TGI>;
 
 public
 constructor Create(AGC: TGenericCollection<TGI>);
 destructor Destroy; override;
 
 function GetCurrent: TGI;
 function MoveNext: Boolean;
 
 property Current: TGI read GetCurrent;
 end;
 ...
 public
 function GetEnumerator: TGCEnumerator; reintroduce;
 ...
 end;
 
 
|  |   Вопрос задал: dmistand (статус: 1-ый класс)Вопрос отправлен: 11 декабря 2013, 16:27
 Состояние вопроса: решён, ответов: 0.
 |  
 Мини-форум вопросаВсего сообщений: 9; последнее сообщение — 31 мая 2015, 22:22; участников в обсуждении: 3. 
|   | min@y™ (статус: Доктор наук), 11 декабря 2013, 16:59 [#1]:Почему на скриншоте я не вижу ни одной попытки поставить брейк? Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп! |  
|   | dmistand (статус: 1-ый класс), 11 декабря 2013, 17:42 [#2]:min@y™: Если вы прочтёте статью, ссылку на которую я специально для этого указал в скобках, вы будете знать, что синие точки как раз и означают те места, где можно поставить BP. Но если очень важно присутствие на картинке голубых и зелёных полос, то вот, поставил аж 4 ВР: http://cs310226.vk.me/v310226434/5b33/GZwAanxaqtk.jpg |  
|   | min@y™ (статус: Доктор наук), 12 декабря 2013, 08:22 [#3]: Цитата (dmistand): Если вы прочтёте статью, ссылку на которую я специально для этого указал в скобках, вы будете знать, что синие точки как раз и означают те места, где можно поставить BP. 
  Пипец! Вот это поворот! 
 Цитата (dmistand): Но если очень важно присутствие на картинке голубых и зелёных полос, то вот, поставил аж 4 ВР: Ну и чего ж тебя не устраивает?
 
 Цитата (dmistand): это нельзя сделать даже на точке входа в метод. Почему? А потому что ты думаешь, что слово "begin" - это точка входа в метод. А это всего лишь операторная скобка.
 Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп! |  
|   | dmistand (статус: 1-ый класс), 12 декабря 2013, 17:49 [#4]:min@y™: хорошо, пусть так. Но это не решает проблему и не отвечает на вопрос. Если это лишь операторная скобка (это я понимаю), то почему в одних методах на неё можно поставить ВР, а в других - нельзя? 
 А по поводу изначального вопроса я добавил примечание. Спасибо за понимание и помощь.
 |  
|   | min@y™ (статус: Доктор наук), 13 декабря 2013, 08:33 [#5]: Цитата (dmistand): Если это лишь операторная скобка (это я понимаю), то почему в одних методах на неё можно поставить ВР, а в других - нельзя?  А вот не знаю. Это вопрос, скорее, к авторам отладчика. Но про подобные глюки поздних версий Delphi я уже слышал.
 Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп! |  
|   | dmistand (статус: 1-ый класс), 13 декабря 2013, 09:36 [#6]:min@y™: то есть по примечанию #2 у вас нет комментариев? |  
|   | min@y™ (статус: Доктор наук), 13 декабря 2013, 10:11 [#7]: Цитата (dmistand): то есть по примечанию #2 у вас нет комментариев?  Нет: с такой ситуацией не сталикивался.
 Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп! |  
|   | dmistand (статус: 1-ый класс), 13 декабря 2013, 10:59 [#8]:min@y™: эх... В любом случае спасибо за беспокойство. |  13 декабря 2013, 16:01: Статус вопроса изменён на решённый (изменил автор вопроса — dmistand) 13 декабря 2013, 16:02: Вопрос вновь открыт (изменение состояния произвёл автор вопроса — dmistand) 13 декабря 2013, 16:12: Статус вопроса изменён на решённый (изменил автор вопроса — dmistand) 
|   | Сергей Монро (статус: Заблокирован), 31 мая 2015, 22:22 [#9]:<a href="http://fotostydia.ru/posts/889933">Фотосессия на природе для красивых девушек.</a> |  Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте. |