4Gbマシンの64ビットLinux OSで次のコードを実行しています。
package main
import (
"fmt"
"math"
)
func main() {
r := make([]bool, math.MaxInt32)
fmt.Println("Size: ", len(r))
}
これを実行すると、次のようになります。
Size: 2147483647
math.MaxInt32
のmath.MaxUint32
を変更すると、次のようになります。
fatal error: runtime: out of memory
スライスサイズがmath.MaxUint32
の場合、メモリ不足になりそうでしたが、math.MaxInt64
を使用すると次のようになります。
panic: runtime error: makeslice: len out of range
どうやら私はmath.MaxInt64
のサイズでスライスを作成することができないので、私に質問を投げかけます。メモリに問題がない場合、Goで作成できない最大のスライスは何ですか?
Javaでは、生の配列インデックスはint
型で管理されるので、生の配列の最大サイズはint
の最大値です。 long
(私が覚えている限り)例外が発生します。Goと同じですか? Goのスライスインデックスは1つの特定のタイプにバインドされていますか?
編集:
bool
の代わりにstruct{}
を使用してテストを実行し、math.MaxInt64
要素を割り当てました。すべてが期待通りに進み、印刷されます:
Size: 9223372036854775807
では、別の質問ですが、エラーが同じ(メモリ不足)のように思われるのに、なぜ2つの異なるエラーメッセージが表示されるのでしょうか。
各エラーがポップアウトする条件は何ですか?
ドキュメントによると、The elements can be addressed by integer indices 0 through len(s)-1
。これは、スライスの最大容量がターゲットビルドのデフォルトの整数のサイズであることを意味します。
編集:ソースコードを見ると、このサイズのスライスが可能な限り確実であることを確認する安全チェックがあるようです:
_func makeslice(t *slicetype, len64 int64, cap64 int64) sliceStruct {
// NOTE: The len > MaxMem/elemsize check here is not strictly necessary,
// but it produces a 'len out of range' error instead of a 'cap out of range' error
// when someone does make([]T, bignumber). 'cap out of range' is true too,
// but since the cap is only being supplied implicitly, saying len is clearer.
// See issue 4085.
len := int(len64)
if len64 < 0 || int64(len) != len64 || t.elem.size > 0 && uintptr(len) > maxmem/uintptr(t.elem.size) {
panic(errorString("makeslice: len out of range"))
}
_
したがって、この場合はuintptr(len) > maxmem/uintptr(t.elem.size)
のように見えるため、このサイズの割り当てを行うことはできません。
ただし、メモリを消費しない_struct{}
_を割り当てると、このサイズが許可されます。
_func main(){
r := make([]struct{}, math.MaxInt64)
fmt.Println(len(r))
}
// prints 9223372036854775807
_