Утечка памяти с помощью WMI в Delphi 7

Самое лучшее решение, которое я нашел, - это сделать следующее в контроллере первого вида .

Objective-C

- (void)viewWillAppear:(BOOL)animated {
    [self.navigationController setNavigationBarHidden:YES animated:animated];
    [super viewWillAppear:animated];
}

- (void)viewWillDisappear:(BOOL)animated {
    [self.navigationController setNavigationBarHidden:NO animated:animated];
    [super viewWillDisappear:animated];
}

Swift

override func viewWillAppear(animated: Bool) {
    self.navigationController?.setNavigationBarHidden(true, animated: animated)
    super.viewWillAppear(animated)
}

override func viewWillDisappear(animated: Bool) {
    self.navigationController?.setNavigationBarHidden(false, animated: animated)
    super.viewWillDisappear(animated)
} 

Это приведет к анимированию навигационной панели слева ( вместе со следующим представлением), когда вы нажимаете следующий UIViewController в стеке, и анимируете влево (вместе со старым представлением), когда вы нажимаете кнопку возврата на UINavigationBar.

Также обратите внимание, что это не делегированные методы, вы переопределяете реализацию этих методов UIViewController, и согласно документации вы должны вызывать реализацию super где-то в вашей реализации .

5
задан Rob Kennedy 25 June 2009 в 14:52
поделиться

2 ответа

Я могу воспроизвести поведение, код утечка памяти в Windows XP 64 и не в Windows XP. Интересно, что это происходит только при чтении свойства Path_ , чтение Properties_ или Security_ с тем же кодом не приводит к утечке памяти. Проблема с версией Windows в WMI выглядит наиболее вероятной причиной этого. Моя система обновлена ​​AFAIK, так что, вероятно, для этого тоже нет исправления.

Я хотел бы прокомментировать ваш сброс всех переменных вариантов и интерфейса. Вы пишете

. Несколько раз вы заметите, что nil присваивается объектам, вопреки духу Delphi ... Это COM-объекты, которые не наследуются от TObject и не имеют деструктора, который я могу вызвать. Присваивая им nil, Windows ' s сборщик мусора очищает их.

Это неверно, и, следовательно, нет необходимости устанавливать переменные в nil и Unassigned . В Windows нет сборщика мусора, вы имеете дело с объектами со счетчиком ссылок, которые немедленно уничтожаются, как только счетчик ссылок достигает 0. Компилятор Delphi вставляет необходимые вызовы для увеличения и уменьшения счетчика ссылок по мере необходимости. Ваши назначения nil и Unassigned уменьшают счетчик ссылок и освобождают объект, когда он достигает 0.

Новое присвоение переменной или выход из процедуры позаботьтесь о этого тоже, поэтому дополнительные присваивания (хотя и не ошибочно) излишни и уменьшают ясность кода. Следующий код полностью эквивалентен и не вызывает утечки дополнительной памяти:

procedure ProcessObjectSet(WMIObjectSet: ISWbemObjectSet);
var
  Enum: IEnumVariant;
  tempObj: OleVariant;
  Value: Cardinal;
  sObject: ISWbemObject;
begin
  Enum := (wmiObjectSet._NewEnum) as IEnumVariant;
  while (Enum.Next(1, tempObj, Value) = S_OK) do
  begin
    sObject := IUnknown(tempObj) as SWBemObject;
    { Leak! }
    sObject.Path_;
  end;
end;

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

7
ответ дан 14 December 2019 в 08:58
поделиться

вы должны сохранить возвращаемое значение

sObject.Path_;

в переменной и сделать его SWbemObjectPath. Это необходимо для правильного подсчета ссылок.

0
ответ дан 14 December 2019 в 08:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: