2014-12-25 13 views
7

Mam następujący kod działa w 64-bitowym systemie operacyjnym Linux w komputerze 4Gb:Maksymalna długość segmentu w Go

package main 

import (
    "fmt" 
    "math" 
) 

func main() { 
    r := make([]bool, math.MaxInt32) 

    fmt.Println("Size: ", len(r)) 
} 

Kiedy uruchamiam to uzyskać:

Size: 2147483647 

Jeśli I zmienić math.MaxInt32 dla math.MaxUint32 uzyskać:

fatal error: runtime: out of memory 

z wielkości wlewu math.MaxUint32 Pobiegłem z pamięci, spodziewałem się tego, ale gdy próbuję za pomocą math.MaxInt64 uzyskać:

panic: runtime error: makeslice: len out of range 

Więc aparently Nie mogę utworzyć kawałek o wielkości math.MaxInt64, która doprowadzi nas do mojego pytania: Jeśli pamięć nie jest problem, jaki jest największy kawałek, którego nie mogę stworzyć w Go?

Pamiętam, że w Javie, surowe indeksy tablicy są zarządzane z typem int, więc maksymalna wielkość surowego tablicy jest wartość max o int, jeśli starają się zrobić z long to podniesie wyjątek (o ile pamiętam), czy tak samo jest z Go? są indeksem plastra w Go powiązanym z jednym określonym typem?

EDIT:

Pobiegłem test używając struct{} zamiast bool i przydzielanie math.MaxInt64 elementy. Wszystko poszło zgodnie z oczekiwaniami, a drukuje:

Size: 9223372036854775807 

Więc kolejne pytanie, dlaczego istnieją dwa różne komunikaty o błędach, gdy wydaje się, że błąd jest taki sam (mało pamięci)?

Jakie są warunki wyskakiwania każdego błędu?

+0

Wygląda więc na to, że jest to kwestia komunikatu o błędzie niejednoznaczności, nic więcej ... :) –

Odpowiedz

10

Według dokumentów, The elements can be addressed by integer indices 0 through len(s)-1. Oznacza to, że maksymalna wielkość plasterka to wielkość domyślnej liczby całkowitej na docelowej kompilacji.

EDIT: Od patrząc na kod źródłowy, wydaje się, że istnieje kontrola bezpieczeństwa, aby upewnić się, że wielkość wycinka jest w ogóle możliwe:

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")) 
    } 

Więc w tym przypadku, to wygląda uintptr(len) > maxmem/uintptr(t.elem.size) tak nie możemy wykonywać tej wielkości przydziału.

Jednak kiedy przeznaczyć struct{} który trwa nie pamięta, to wielkość jest dozwolone: ​​

func main(){ 
    r := make([]struct{}, math.MaxInt64) 
    fmt.Println(len(r)) 
} 
// prints 9223372036854775807 
+0

Jestem pewien, że Uruchamiam 64-bitową wersję Go, jeśli wykonuję 'go version', to drukuje' go version go1.4 linux/amd64' –

+0

@ SimonOroño co znaczy "go env" wydrukować dla GOARCH? –

+0

@ SimonOroño Sprawdziłem kod źródłowy Go i myślę, że znam ten problem. Aktualizuję moją odpowiedź. –