一次ソースはこちら→ 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に渡すのも基本ダメ
-
こちらで定義されているのの直訳→ we define a Go pointer to be a pointer to Go memory ↩
-
自動で移動するようになるかもって書いてある→ If a later garbage collector implements moving pointers, ↩
-
be pinned
と書いてある箇所を「保護」と訳しました。こちら参照→ https://github.com/golang/proposal/blob/a3c90bbfd94cdec0c55c97d320e6707c64ac9f64/design/12416-cgo-pointers.md#consequences ↩