Почему блок «Меню» доработан слишком рано? - PullRequest
1 голос
/ 26 марта 2010

Я протестировал свое приложение с включенным FastMM и FullDebugMode, так как у меня были некоторые проблемы с завершением работы.

После решения множества моих собственных проблем FastMM начал жаловаться на вызов виртуального метода для освобожденного объекта в TPopupList. Я попытался переместить блок меню как можно раньше при использовании, чтобы он был завершен последним, но это не помогло. Это настоящая проблема, ошибка в vcl или ложная тревога от FastMM?

Вот полный отчет FastMM:

FastMM has detected an attempt to call a virtual method on a freed object. An access violation will now be raised in order to abort the current operation.

Freed object class: TPopupList

Virtual method: Offset +16

Virtual method address: 4714E4

The allocation number was: 220

The object was allocated by thread 0x1CC0, and the stack trace (return addresses) at the time was:
403216 [sys\system.pas][System][System.@GetMem][2654]
404A4F [sys\system.pas][System][System.TObject.NewInstance][8807]
404E16 [sys\system.pas][System][System.@ClassCreate][9472]
404A84 [sys\system.pas][System][System.TObject.Create][8822]
7F2602 [Menus.pas][Menus][Menus.Menus][4223]
40570F [sys\system.pas][System][System.InitUnits][11397]
405777 [sys\system.pas][System][System.@StartExe][11462]
40844F [SysInit.pas][SysInit][SysInit.@InitExe][663]
7F6368 [PCCSServer.dpr][PCCSServer][PCCSServer.PCCSServer][148]
7C90DCBA [ZwSetInformationThread]
7C817077 [Unknown function at RegisterWaitForInputIdle]

The object was subsequently freed by thread 0x1CC0, and the stack trace (return addresses) at the time was:
403232 [sys\system.pas][System][System.@FreeMem][2699]
404A6D [sys\system.pas][System][System.TObject.FreeInstance][8813]
404E61 [sys\system.pas][System][System.@ClassDestroy][9513]
428D15 [common\Classes.pas][Classes][Classes.TList.Destroy][2914]
404AB3 [sys\system.pas][System][System.TObject.Free][8832]
472091 [Menus.pas][Menus][Menus.Finalization][4228]
4056A7 [sys\system.pas][System][System.FinalizeUnits][11256]
4056BF [sys\system.pas][System][System.FinalizeUnits][11261]
7C9032A8 [RtlConvertUlongToLargeInteger]
7C90327A [RtlConvertUlongToLargeInteger]
7C92AA0F [Unknown function at towlower]

The current thread ID is 0x1CC0, and the stack trace (return addresses) leading to this error is:
4714B8 [Menus.pas][Menus][Menus.TPopupList.MainWndProc][3779]
435BB2 [common\Classes.pas][Classes][Classes.StdWndProc][11583]
7E418734 [Unknown function at GetDC]
7E418816 [Unknown function at GetDC]
7E428EA0 [Unknown function at DefWindowProcW]
7E428EEC [Unknown function at DefWindowProcW]
7C90E473 [KiUserCallbackDispatcher]
7E42B1A8 [DestroyWindow]
47CE31 [Controls.pas][Controls][Controls.TWinControl.DestroyWindowHandle][6857]
493BE4 [Forms.pas][Forms][Forms.TCustomForm.DestroyWindowHandle][4564]
4906D9 [Forms.pas][Forms][Forms.TCustomForm.Destroy][2929]

Current memory dump of 256 bytes starting at pointer address 7FF9CFF0:
2C FE 82 00 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 C4 A3 2D 0C 00 00 00 00 B1 D0 F9 7F
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C0 00 00 00 16 32 40 00 9D 5B 40 00 C8 5B 40 00
CE 82 40 00 3C 40 91 7C B0 B1 94 7C 0A 77 92 7C 84 77 92 7C 7C F0 96 7C 94 B3 94 7C 84 77 92 7C
C0 1C 00 00 32 32 40 00 12 5B 40 00 EF 69 40 00 BA 20 47 00 A7 56 40 00 BF 56 40 00 A8 32 90 7C
7A 32 90 7C 0F AA 92 7C 0A 77 92 7C 84 77 92 7C C0 1C 00 00 0E 00 00 00 00 00 00 00 C7 35 65 59
2C FE 82 00 80 80 80 80 80 80 80 80 80 80 38 CA 9A A6 80 80 80 80 80 80 00 00 00 00 51 D1 F9 7F
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C1 00 00 00 16 32 40 00 9D 5B 40 00 C8 5B 40 00
CE 82 40 00 3C 40 91 7C B0 B1 94 7C 0A 77 92 7C 84 77 92 7C 7C F0 96 7C 94 B3 94 7C 84 77 92 7C
,  þ  ‚  .  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  Ä  £  -  .  .  .  .  .  ±  Ð  ù  
.  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  À  .  .  .  .  2  @  .    [  @  .  È  [  @  .
Î  ‚  @  .  <  @  ‘  |  °  ±  ”  |  .  w  ’  |  „  w  ’  |  |  ð  –  |  ”  ³  ”  |  „  w  ’  |
À  .  .  .  2  2  @  .  .  [  @  .  ï  i  @  .  º     G  .  §  V  @  .  ¿  V  @  .  ¨  2    |
z  2    |  .  ª  ’  |  .  w  ’  |  „  w  ’  |  À  .  .  .  .  .  .  .  .  .  .  .  Ç  5  e  Y
,  þ  ‚  .  €  €  €  €  €  €  €  €  €  €  8  Ê  š  ¦  €  €  €  €  €  €  .  .  .  .  Q  Ñ  ù  
.  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  Á  .  .  .  .  2  @  .    [  @  .  È  [  @  .
Î  ‚  @  .  <  @  ‘  |  °  ±  ”  |  .  w  ’  |  „  w  ’  |  |  ð  –  |  ”  ³  ”  |  „  w  ’  |

Я использую Delphi 2007 и FastMM 4.97.

Edit1: Я думаю, что главная проблема здесь в том, почему Classes.StdWndProc вызывает Menus.TPopupList? Копание стека вызовов в отладчике показывает, что System.FinalizeUnit вызывается три раза, затем он переходит к SysUtils.ShowException, который пытается отобразить MessageBox, и после нескольких вызовов user32.dll мы получаем классы.StdWndProc.

Edit2: У меня была проблема с интерфейсами, исправление которой устранило эту проблему. Объект с интерфейсом был освобожден, но ссылка была освобождена позже. Когда интерфейс был выпущен, произошло исключение, которое я изначально как-то игнорировал. Освобождение интерфейса, вероятно, повредило что-то, что вызвало все другие проблемы.

Ответы [ 5 ]

7 голосов
/ 26 марта 2010

Такая ситуация может возникать, когда юнит завершает работу после другого юнита, от которого он косвенно зависит.

Например, возьмите следующую единицу:

unit Unit1;
interface
uses
  Contnrs;

var
  ItemHolder : TObjectList;

implementation

initialization
  ItemHolder := TObjectList.Create(True);
finalization
  ItemHolder.Free;
end.

Эта единица напрямую зависит только от Contnrs. По этой причине delphi будет гарантировать, что этот модуль будет завершен до завершения Contnrs. Если ObjectList содержит TForms, Delphi не будет гарантировать, что Unit1 будет завершен до Forms Unit. Если при закрытии приложения все еще остаются некоторые формы, TObjectList (поскольку он владеет объектом) освободит содержащиеся в нем элементы (Call TForm.Free). Но поскольку Unit1 не зависит от TForm, вполне возможно, что формы юнитов уже завершены и TForm.Destroy больше не находится в памяти.

Вот почему вам нужно быть очень осторожным с тем, что вы делаете в разделах финализации.

Я не уверен, что это источник вашей проблемы, но я бы сначала посмотрел так.

3 голосов
/ 26 марта 2010

Я видел такие проблемы с Delphi 2007 раньше. Иногда компилятор запутывается и генерирует неправильный порядок инициализации или завершения. К сожалению, мне так и не удалось создать воспроизводимый контрольный пример для отправки сотрудникам CodeGear / Embarcadero.

Всякий раз, когда это происходило, помогала полная перестройка.

2 голосов
/ 26 марта 2010

Похоже, что одна из ваших форм разрушается после завершения работы над Menus.pas. Если в вашей форме есть меню, возможно, в ее списке в разделе interface меню должно быть меню, что сделает это невозможным.

Единственный раз, когда я видел подобные всплывающие окна (без каламбура), это при использовании пакетов. Возможно, вы используете DPK с плагином, который добавляет всплывающее меню или пункты меню в вашу программу? Завершение пакета может сделать некоторые странные вещи с вашей программой, если вы не будете осторожны.

В любом случае, решение, вероятно, состоит в том, чтобы самостоятельно утилизировать меню до того, как menus.pas завершит работу. Когда пора завершить работу программы, вызовите Free во всплывающем меню и посмотрите, решит ли это проблему.

2 голосов
/ 26 марта 2010

Убедитесь, что FastMM4 - это ПЕРВАЯ строка в предложении использования файла вашего проекта (проект | Просмотр источника). Если его нет, добавьте его.

0 голосов
/ 06 апреля 2011

Обновление: это только частичный обходной путь

Обход: В основной форме заявки напишите

finalization
  FreeAndNil(PopupList);
end.

этот бесплатный PopupList и установлен в ноль, поэтому PopupList.Free в menus.pas будет в порядке.

...