|
Вопрос # 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>
|
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|