Edited at

Go 1.6 でポインタをcgoの関数へ渡す際の注意点

More than 3 years have passed since last update.

一次ソースはこちら→ https://github.com/golang/proposal/blob/master/design/12416-cgo-pointers.md そのうち誰かが訳してくれると信じています


前提


  • この記事では、Goで確保されたメモリへのポインタをGoポインタとする1

  • この記事を書いている時点では、Go1.6はbeta2のため、まだ変わるかもしれない

  • Goで確保されたメモリはGCされたり、将来的には自動で移動するようになるかもしれない2

  • C側で確保されたメモリはGCされない。将来的な自動移動も行われない


Go1.6からどうなるか


  • Goポインタをcgoの関数へ引数として渡すと、そのcgoの関数から返ってくるまでそのポインタが指すメモリは保護3されGCされたり移動したりしなくなる


そのため、下記の点を注意する必要があります


  • cgoの関数の引数経由以外の方法でGoポインタをCに渡した場合は、そのGoポインタが指すメモリは保護されない

  • cgoの関数から返ってくると保護されていたGoポインタの保護も外れるため、cgoの関数内でGoポインタをどこかに保存して次に呼ばれたcgoの関数内で再利用とかはできない

  • GoポインタへのGoポインタをcgoの関数に渡すのは基本ダメ


    • 保護されるのは引数で渡されたGoポインタが指す先のみで、その指す先の更に指す先は保護されない

    • go1.6beta2では、cgo関数呼び出し時のチェックに引っかかってcgo argument has Go pointer to Go pointerというエラーメッセージが表示される

    • Cで確保されたメモリへのポインタへのGoポインタならOK。Cで確保されたメモリはGC対象ではないため



  • GoポインタへのGoポインタがダメなのと同じ理由で、Goポインタをフィールドに持つ構造体へのGoポインタをcgoに渡すのも基本ダメ






  1. こちらで定義されているのの直訳→ we define a Go pointer to be a pointer to Go memory 



  2. 自動で移動するようになるかもって書いてある→ If a later garbage collector implements moving pointers, 



  3. be pinnedと書いてある箇所を「保護」と訳しました。こちら参照→ https://github.com/golang/proposal/blob/a3c90bbfd94cdec0c55c97d320e6707c64ac9f64/design/12416-cgo-pointers.md#consequences