Нарушение прав доступа при использовании DocumentElement в XMLDocument

Я всегда получаю нарушение прав доступа, когда пытаюсь использовать DocumentElement из XMLDocument. Я создаю XMLDocument на основании существования какого-то файла.

Сообщение об ошибке

Project project1.exe вызвал класс исключения EAccessViolation с сообщением «Нарушение доступа по адресу 0047B152 в модуле project1.exe». Чтение адреса B1D59357 »

Мой код

unit XMLBase;

interface
uses
  SysUtils, xmldom, XMLIntf, XMLDoc, Forms;

type
  TXMLbase = class
  private
    { Private declarations }
  public
    XMLDocument1: TXMLDocument;
    root: IXMLNode;    
    constructor Create;
  end;

var
  fn: string;

implementation

constructor TXMLbase.Create;
begin   
  fn := ChangeFileExt(Application.ExeName, '.xml');
  XMLDocument1 := TXMLDocument.Create(nil);
  XMLDocument1.Options := [doNodeAutoIndent];
  XMLDocument1.Active := False;
  //optional, is used to indent the Xml document
  if FileExists(fn) then
  begin
  XMLDocument1.LoadFromFile(fn);
  XMLDocument1.Active:= True;
  root := XMLDocument1.DocumentElement;  //<<--- Access Voilation
  end
  else
  begin
    XMLDocument1.Active := False;
    XMLDocument1.XML.Text := '';
    XMLDocument1.Active := True;
    root := XMLDocument1.AddChild('Settings');    
  end;
XMLDocument1.SaveToFile(fn);
end;

end.

Нарушения доступа возникают из-за неправильной инициализации объекта или указателей. Означает ли это, что XMLDocument не инициализируется?


person Jatin Gera    schedule 25.12.2012    source источник
comment
код прерывается в строке 32, а root объявляется в публичной секции   -  person Jatin Gera    schedule 25.12.2012
comment
Что ж, когда я тестирую настоящий XML-документ, я получаю Invalid pointer operation без определенной точки останова после завершения работы конструктора.   -  person Jerry Dodge    schedule 25.12.2012
comment
Код работает нормально, когда нет XML-документа, и он создает единственный узел '‹Settings /›', однако при повторном запуске он прерывается, любая попытка чтения выполняется для элемента документа.   -  person Jatin Gera    schedule 25.12.2012
comment
Если все, что вы делаете, это какие-то настройки приложения, может ли INI File работать для того, что вам нужно? XML - это немного, если вам просто нужно сохранить несколько строк, но он отлично подходит, когда у вас есть сложная группа настроек.   -  person Jerry Dodge    schedule 25.12.2012
comment
Можете ли вы проверить свой XML-документ на соответствие его XML-схеме (xsd)?   -  person Jack G.    schedule 25.12.2012
comment
@ J.Gonzalez Не похоже, что он использует схему.   -  person Jerry Dodge    schedule 25.12.2012
comment
Что ж, если бы проблема была в самом XML-коде, сообщение об ошибке было бы более специфичным для XML, а не для аудио / видео. Это весь ваш полный код? Или есть что-то, что вы удалили, чтобы опубликовать здесь?   -  person Jerry Dodge    schedule 25.12.2012
comment
@ Jerry Dodge. Раньше я использовал Ini-файл, но я хочу сохранить много вещей, которые не поддерживает ini-файл, например, большой объем текста.   -  person Jatin Gera    schedule 25.12.2012
comment
Есть шанс создать схему XML, а затем использовать мастер XML для доступа к ней, что было бы проще, чем перебирать узлы XML, и гарантировать отображение Delphi / XML.   -  person Jack G.    schedule 25.12.2012
comment
вы можете получить его на [ссылка] rapidshare.com/files/1056241858/Project.7z [ссылка]   -  person Jatin Gera    schedule 25.12.2012
comment
Загрузка @XPecto недоступна: неверный идентификатор файла   -  person Jerry Dodge    schedule 26.12.2012
comment
Google Диск [ссылка] docs.google.com/open?id=0Bw9D_3GJ- a48WnFTaGRjd1lSY2c [ссылка] Rapidshare Ссылка: [ссылка] rapidshare.com/files /1056241858/Project.7z[ссылка]   -  person Jatin Gera    schedule 26.12.2012


Ответы (2)


Как указал Дэвид, простое изменение объявления XMLDocument1 с XMLDocument1: TXMLDocument на XMLDocument1: IXMLDocument решает проблему. Ваша проблема связана с использованием TXmlDocument

person Jack G.    schedule 25.12.2012
comment
Разве это не просто повторение одного из вариантов, которые я дал, и опускание деталей? - person David Heffernan; 26.12.2012
comment
@David Первоначальный пост не дал прямого решения проблемы (просто изменил XMLDocument1: IXMLDocument). Третье редактирование делает. Приносим извинения за публикацию между первым и третьим редактированием. Как это исправить? - person Jack G.; 26.12.2012
comment
Исходный пост включал оба возможных решения. - person David Heffernan; 26.12.2012
comment
Думаю, XPecto нужно было разобрать это с помощью кода. И я, наверное, пренебрегал этим в пользу многословного изложения. Так что, наверное, на мне. :-) - person David Heffernan; 26.12.2012

Вы передаете nil TXMLDocument.Create. Когда вы это делаете, объект ведет себя как TInterfacedObject. Его время жизни управляется подсчетом ссылок на интерфейс. Но вы не держите ссылку на интерфейс.

Это более подробно рассматривается в документации.

Когда TXMLDocument создается без владельца, он ведет себя как интерфейсный объект. То есть, когда все ссылки на его интерфейс освобождаются, экземпляр TXMLDocument автоматически освобождается. Однако когда TXMLDocument создается с владельцем, он ведет себя как любой другой компонент и освобождается его владельцем.

Если вы включите Debug DCU и установите точку останова в TXMLDocument.Destroy, вы увидите, как объект уничтожается непосредственно перед нарушением прав доступа.

Решите проблему одним из следующих способов:

  1. Передача владельца при создании документа.
  2. Переключитесь на использование интерфейсов для ссылки на объект. То есть объявить XMLDocument1 как IXMLDocument.

Убедитесь, что вы делаете одно из них, но не то и другое одновременно!

person David Heffernan    schedule 25.12.2012
comment
Понимаете, я бы никогда этого не обнаружил. Слава Богу за людей, которые знают больше о внутреннем устройстве. - person Jerry Dodge; 25.12.2012
comment
Я изменил конструктор по умолчанию на constructor Create(Owner:TObject); и передал его из формы как x:= TXMLbase.Create(Self);, но у меня такая же проблема. не могли бы вы показать какой-нибудь пример, спасибо. - person Jatin Gera; 25.12.2012
comment
Это каким-то образом объясняет, по крайней мере, немного, почему я получаю Invalid pointer operation, а вы Access violation - person Jerry Dodge; 25.12.2012
comment
Этого не достаточно! Вы должны передать владельца конструктору TXMLDocument! Как это: XMLDocument1 := TXMLDocument.Create(Owener). - person David Heffernan; 25.12.2012
comment
Итак, я посмотрел немного глубже. Я на 100% уверен, что мой ответ объясняет вашу проблему. - person David Heffernan; 25.12.2012