GCとiterator

Giraffe+ 0.6.5.899で、

get-cb.filtered(`c[c.isalpha]).flush

access violation。
get-cbはクリップボードの文字列を返す。filteredはfilter_iteratorのRangeを返す。flushの時点で、get-cbが返したオブジェクトがGCに開放されてる可能性がある。実際には、クリップボードの文字列が大きいとGCが積極的に開放してしまう。
iteratorが保持するのは、(STLの実装に寄るが)thisが保持するメモリブロックへの参照であって、thisそのものではないため。
この、iteratorのみが参照可能な状態でthisが開放される問題を解決するには、

  1. GC_allocatorを使う - そのメモリブロックがGCで生成されていれば、iteratorが参照可能である限りそのメモリブロックも開放されない。
  2. iteratorにthisを保持させる - iteratorからthisが参照可能なら、iteratorが参照可能な限りthisは開放されない。
  3. ユーザに気を付けてもらう - 最終手段

3は解決ではなく妥協なので論外として、1か2になるが、2はSTLの実装に手を入れる必要があり、1はbasic_stringのallocatorを置き換えるだけでいい。
1が妥当に思えるが、std::string, wstring以外を使うと、対応してないライブラリ等があったりして、不都合がままある。

gsでは、根本的な解決では無いが、rangeを作る関数にthisを渡して、rangeがiteratorとthisを保持するようにした。
当然iteratorのみで使う場合に問題は残るが、それはそう無い事であり、そういう事には3でいいと結論した。

iteratorはthisを参照してるような気がするが、実際には同じものを参照していて、その参照先の管理をthisのみが担っているということがこの問題の本質になる。