[delphi-users:2217] Re: TXMLDocumentで途中でポインタ例外

130 views
Skip to first unread message

Magical-Soft

unread,
Sep 30, 2011, 1:22:07 AM9/30/11
to delphi...@freeml.com
自己解決しましたが、解せないです。

procedure ReadNode(Node:IXMLNode);
var
i: Integer;
begin
for i=0 to Node.ChildNodes.Count -1 do
begin
if Node.ChildNodes.Nodes[i].HasChildNodes then
ReadNode(Node.ChildNodes.Nodes[i]);
end;
end;

のように再帰させると、なぜか関数を抜ける際にポインタエラーが返ってきます。
やり方間違っているのかなぁ?
try
ReadNode(FXML.Node);
except
end;
でトラップして解決しましたがスマートじゃないよなぁ。


On 2011/09/29, at 14:15, Magical-Soft wrote:

> Magical-Soft 石川です。
>
> ちょっとデータ読むのにXMLDocument使うことにしたのですが、途中でポインタ例外がでてしまいます
>
> XMLっても
> --
> <?xml version="1.0" encoding="UTF-8"?>
> <root>
> <dir title="ポータル">
> <a href="http://www.google.com/">Google</a>
> <a href="http://www.yahoo.co.jp/">Yahoo! JAPAN</a>
> <a href="http://www.infoseek.co.jp/">インフォシーク</a>
> <a href="http://www.excite.co.jp/">Excite エキサイト</a>
> <a href="http://www.livedoor.com/">livedoor</a>
> <a href="http://www.goo.ne.jp/">goo</a>
> <a href="http://jp.msn.com/">MSN Japan</a>
> <a href="http://ja.wikipedia.org/">Wikipedia</a>
> </dir>
> <dir title="ニュース">
> <a href="http://watch.impress.co.jp/">Impress Watch</a>
> <a href="http://www.itmedia.co.jp/">IT総合情報ポータル「ITmedia」Home</a>
> <a href="http://www.nikkeibp.co.jp/">nikkei BPnet〈日経BPネット〉</a>
> <a href="http://ascii.jp/">ASCII.jp</a>
> <a href="http://journal.mycom.co.jp/">マイコミジャーナル</a>
> <a href="http://www.asahi.com/">aasahi.com:朝日新聞社の速報ニュースサイト</a>
> <a href="http://www.yomiuri.co.jp/">ニュース 速報 YOMIURI ONLINE(読売新聞)</a>
> <a href="http://sankei.jp.msn.com/">MSN産経ニュース</a>
> <a href="http://www.nikkei.com/">日本経済新聞</a>
> <a href="http://mainichi.jp/">毎日jp - 毎日新聞のニュース・情報サイト</a>
> <a href="http://www.cnn.co.jp/">CNN.co.jp</a>
> </dir>
> <dir title="TV放送局">
> <a href="http://www.nhk.or.jp/">NHKオンライン</a>
> <a href="http://www.ntv.co.jp/">日本テレビ</a>
> <a href="http://www.tbs.co.jp/">TBSテレビ</a>
> <a href="http://www.fujitv.co.jp/">フジテレビ</a>
> <a href="http://www.tv-asahi.co.jp/">tv asahi|テレビ朝日</a>
> <a href="http://www.tv-tokyo.co.jp/">テレビ東京</a>
> </dir>
> <dir title="ラジオ放送局">
> <a href="http://www.tbs.co.jp/radio/">TBSラジオ</a>
> <a href="http://www.joqr.co.jp/">AMラジオ1134kHz 文化放送 JOQR</a>
> <a href="http://www.1242.com/">AMラジオ 1242 ニッポン放送</a>
> <a href="http://www.radionikkei.jp/">ラジオNIKKEI</a>
> <a href="http://www.tfm.co.jp/">TOKYO FM 80.0MHz - 80.Love FM RADIO STATION</a>
> <a href="http://www.j-wave.co.jp/">81.3 FM J-WAVE WEBSITE</a>
> </dir>
> </root>
> --
> な感じで、dirはネストOKなのですが
>
> 再帰処理で読んでる途中でChildNodes が変になります。(このパターンだとラジオ放送局でエラー)
> ソースコード家に忘れてきたのでのちほど
>
>
>
> MLホームページ: http://www.freeml.com/delphi-users
>
> ----------------------------------------------------------------------
> メールだけでみんなを招待できる便利機能♪
> http://ad.freeml.com/cgi-bin/sa.cgi?id=htGRJ
> -----------------------------------------------------[freeml by GMO]--
>


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
友達の服をこっそり借りちゃお!「おしゃれ泥棒」
http://ad.freeml.com/cgi-bin/sa.cgi?id=htYYp
-----------------------------------------------------[freeml by GMO]--

hosokawa

unread,
Sep 30, 2011, 1:32:33 AM9/30/11
to delphi...@freeml.com
Magical-Soft 石川さん

細川です。

間違ってるかもしれませんが、IXMLNode がインターフェースだからだと思いま
すよ。

_AddRef で参照カウントが上がって、_Release で参照カウントがデクリメント
されますが、参照カウントが 0 になるとオブジェクトは自動廃棄されます。

参照カウントは RefCount で見れたかな?
このあたり、追って見ると良いかもしれません。


Regards,
HOSOKAWA Jun
[S/G] SERIALGAMES Inc.
TEL: 03-5812-0980
FAX: 03-5812-0970
twitter: http://twitter.com/serialgames
twitter: http://twitter.com/flaver_sg
mailto: j...@serialgames.co.jp
fla:ver http://flaver.jp/
WebCapS http://www.serialgames.co.jp/fun.html#WebCapSeria


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
映画『サラリーマンNEO 劇場版(笑)』試写会へご招待!
http://ad.freeml.com/cgi-bin/sa.cgi?id=htZif

hosokawa

unread,
Sep 30, 2011, 2:25:22 AM9/30/11
to delphi...@freeml.com
Magical-Soft 石川さん

細川です。

インターフェースの参照カウントだとしたら問題があるなーと思って、ちょうど
時間があったので試してみましたが、エラーは出ませんね……。

下のようなコードで試しました。
F:\test.xml はメールにあった XML です。
タグの情報が取れているかも確認しましたが、ちゃんと名前と値は取れていまし
た。
別の何かに原因がありそうですね。


procedure ReadNode(Node:IXMLNode);
var
i: Integer;
begin

for i := 0 to Node.ChildNodes.Count -1 do


begin
if Node.ChildNodes.Nodes[i].HasChildNodes then
ReadNode(Node.ChildNodes.Nodes[i]);
end;
end;

procedure TForm2.FormCreate(Sender: TObject);
var
tmpXMLDoc: IXMLDocument;
FS: TFileStream;
begin
tmpXMLDoc := TXMLDocument.Create(nil);

FS := TFileStream.Create('F:\test.xml', fmOpenRead);
try
tmpXMLDoc.LoadFromStream(FS);
finally
FS.Free;
end;

ReadNode(tmpXMLDoc.Node);
end;


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
メンバーで使える掲示板を活用しよう!
http://ad.freeml.com/cgi-bin/sa.cgi?id=htZYB

yang

unread,
Sep 30, 2011, 10:12:48 AM9/30/11
to delphi...@freeml.com
お疲れ様です。

楊です。

■原因推定:
 文字化け!とは、「F:\test.xml 」ファイルの文字コードはちゃんとUTF-8になっていない!

■検証
 ステップ1:上記XMLの内容をUTF-8,SJIS文字コードで
   test_utf8.xml
   test_sjis.xml
 を保存しておきます。
 
 ステップ2:二つファイルを読み込み、
    test_utf8_saved.xml、
    test_sjis_saved.xmlに落とします。

 ステップ3:結果確認。

  結局test_utf8_saved.xmlはちゃんと作られたが、test_sjis_saved.xmlは生成されなかったことがわかりました。

▼ソースコード添付

procedure TForm1.FormCreate(Sender: TObject);


var
tmpXMLDoc: IXMLDocument;
FS: TFileStream;
begin
tmpXMLDoc := TXMLDocument.Create(nil);

FS := TFileStream.Create('D:\temp\test_utf8.xml', fmOpenRead);
try
tmpXMLDoc.LoadFromStream(FS);
tmpXMLDoc.SaveToFile('D:\temp\test_utf8_saved.xml');
finally
FS.Free;
end;


ReadNode(tmpXMLDoc.Node);

FS := TFileStream.Create('D:\temp\test_sjis.xml', fmOpenRead);
try
tmpXMLDoc.LoadFromStream(FS);
tmpXMLDoc.SaveToFile('D:\temp\test_sjis_saved.xml');
finally
FS.Free;
end;

ReadNode(tmpXMLDoc.Node);
end;

procedure ReadNode(Node: IXMLNode);
var
i: Integer;
begin
for i := 0 to Node.ChildNodes.Count - 1 do


begin
if Node.ChildNodes.Nodes[i].HasChildNodes then
ReadNode(Node.ChildNodes.Nodes[i]);
end;
end;

MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
練習や試合の予定調整は「とっとと決め太郎」におまかせ!
http://ad.freeml.com/cgi-bin/sa.cgi?id=hui1r

Magical-Soft

unread,
Sep 30, 2011, 10:14:09 AM9/30/11
to delphi...@freeml.com
Magical-Soft 石川です。

細川様

procedure をfunctionにして、返り値に _AddRef を入れて、0の場合処理をしないで抜けるようにしたら直りました。
たぶん解析で参照している Node.ChildNodes にアクセスした瞬間に不正なポインタ操作エラーが出てえたのかと。
しかしまぁ、参照0になると勝手に消えるのは気づかなかったです。


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
クーポンサイトを選んで検索♪一番おトクなクーポンをGET!
http://ad.freeml.com/cgi-bin/sa.cgi?id=hui2K

中村@ブレーン

unread,
Oct 3, 2011, 11:43:59 PM10/3/11
to delphi...@freeml.com
中村@ブレーンです。

Delphi 7 と XE2 では再現しませんでした。
バージョンは何でしょう?

Magical-Soft さんは書きました:

----------
東京都 日野市 中村拓男


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
メールだけでみんなを招待できる便利機能♪
http://ad.freeml.com/cgi-bin/sa.cgi?id=huZgM

Magical-Soft

unread,
Oct 4, 2011, 8:21:04 AM10/4/11
to delphi...@freeml.com
Magical-Soft 石川です。

Delphi XE2ですね。いろいろ調べたら勝手にFreeされてました。
たぶん最初に参照したところがrootより手前なんじゃないかと思います。
ゆっくり調査してみます。


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
戦国時代の武将達とともに天下統一を目指そう!
http://ad.freeml.com/cgi-bin/sa.cgi?id=hvhxE

Magical-Soft

unread,
Oct 7, 2011, 6:17:30 AM10/7/11
to delphi...@freeml.com
Magical-Soft 石川です。

一応ソース公開します(どうせフリーソフトですし)


FXML : TXMLDocument;

procedure TForm1.ReadBookMarks(ABookMark: String);
var
i, j : Integer;
begin
Log := TStringList.Create;
FXML := TXMLDocument.Create(nil);
FXML.FileName := ABookMark;
FXML.Active := True;
FXML.NodeIndentStr := #$0009;
FXML.Options := [doNodeAutoIndent];
// 存在チェック
if FileExists( ABookMark ) then
begin
Log.Clear;
// XMLを読み込み
FXML.LoadFromFile( ABookMark );

try
Crawler(FXML.Node,PopupActionBar3.Items);
FXML.Free;
except

end;
end;
//Log.SaveToFile(ExtractFilePath(Application.ExeName)+'test.txt',
TEncoding.UTF8);
Log.Free;
end;

function TForm1.Crawler(Node: IXMLNode; ParentMenuItem:TMenuItem):
Integer;
var
i: Integer;
MenuItem: TMenuItem;
Children: IXMLNodeList;
Flag: Boolean;
begin
Flag := False;
Result := Node._AddRef;
try
//Log.Add(Node.NodeName);
if Result > 0 then
begin
Children := Node.ChildNodes;
if Children.Count > 0 then
for i := 0 to Children.Count - 1 do
begin
if Children.Nodes[i].NodeName = 'root' then
begin
if Children.Nodes[i].HasChildNodes then
Crawler(Children.Nodes[i],ParentMenuItem);
end else
if Children.Nodes[i].NodeName = 'dir' then
begin
//Log.Add(Children.Nodes[i].Attributes['title']);
MenuItem := TMenuItem.Create(self);
MenuItem.Caption := Children.Nodes[i].Attributes['title'];
MenuItem.ImageIndex := 1;
//MenuItem.SubMenuImages := ImageList4;
ParentMenuItem.Add(MenuItem);
BookMarkItemList.Add(MenuItem);
if Children.Nodes[i].HasChildNodes then
try
if Crawler(Children.Nodes[i],MenuItem) = 0 then Flag :=
True;
except
end;
end else
if Children.Nodes[i].NodeName = 'hr' then
begin
//Log.Add('--');
MenuItem := TMenuItem.Create(self);
MenuItem.Caption := '-';
ParentMenuItem.Add(MenuItem);
BookMarkItemList.Add(MenuItem);
end else
if Children.Nodes[i].NodeName = 'a' then
begin
//Log.Add(Node.ChildNodes.Nodes[i].Attributes['href']);
if Children.Nodes[i].NodeValue <> null then
begin
//Log.Add(Children.Nodes[i].NodeValue);
MenuItem := TMenuItem.Create(self);
MenuItem.Caption := Children.Nodes[i].NodeValue;
MenuItem.Hint := Children.Nodes[i].Attributes['href'];
MenuItem.ImageIndex := 0;
MenuItem.OnClick := BookMarkAction1Execute;
ParentMenuItem.Add(MenuItem);
BookMarkItemList.Add(MenuItem);
end else
begin
//Log.Add(' ');
end;
end;
end;
end;
finally
end;
end;


中村@ブレーン <delphi...@freeml.com>さん:


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
練習や試合の予定調整は「とっとと決め太郎」におまかせ!
http://ad.freeml.com/cgi-bin/sa.cgi?id=hvYgE

Reply all
Reply to author
Forward
0 new messages