読者です 読者をやめる 読者になる 読者になる

本当は怖い情報科学

情報系大学院生の趣味&実益ブログ。

ライブラリの使いやすさ:文脈に特化した仕様には注意(libxml-rubyのバグフィックスをしていて思ったこと)

最近libxml-rubyのソースをずっと追いかけていて、libxmlは使いにくいライブラリだなー、と感覚的に思った。その理由を少し考えてみる。

ついでに書くと、今回調べていた問題は、メモリ関係の問題(おそらく2重開放)でsegmentation faultする、という問題だった。数日の格闘の後にMLへパッチを投げたのだが、なにぶんコア開発者の手元では再現しないそうなので、取り入れられるかは微妙。

さて、このSEGV問題の背景に、libxmlの使いにくさがあると思っているわけだ。

少し解説すると、問題はlibxmlの中のaddChildNodeという関数の使い方にあった。この関数の使い方を、ドキュメントから抜粋してみよう(翻訳はkeisukefukudaによる)。

xmlNodePtr xmlAddChild (xmlNodePtr parent, xmlNodePtr cur)

Add a new node to @parent, at the end of the child (or property) list
merging adjacent TEXT nodes (in which case @cur is freed) If the new 
node is ATTRIBUTE, it is added into properties instead of children. 
If there is an attribute with equal name, it is first destroyed.

引数parentに新しいノードを加える。子ノード(または属性)のリストの末尾に
挿入される。テキストノードの場合は一体化され、そのノード(第2引数cur)は
開放される。属性の場合は属性リストに追加され、同名の属性は、最初のものが
破棄される。

まず、ドキュメントの説明文からしてわかりにくいが、問題点は2つ。

単に理解不足という説もあるが、何故にノードと属性を同一視するのか?

  • 煩雑な場合分けに基づく余計なお世話

第二引数がテキストノードの場合はオブジェクトを開放する、というのがいかにも余計なお世話。特定のシチュエーションなら便利なのかも知れないが、一般論としてはバグの元。今回の問題も、直接の原因はこれ。C言語の標準ライブラリのreallocにも同様の問題があって悪名高い。

というわけで、いつも似たようなことを書いているのだが、「使いやすいライブラリ」というのを明確に定義するには、やっぱりたくさんのライブラリを使った経験に基づくしかないのかな。
将来まとめる時のためにメモっておくエントリーでした。

【広告】