[インデックス 16694] ファイルの概要
このコミットは、Go言語の標準ライブラリである sort
パッケージ内のテストファイル src/pkg/sort/sort_test.go
における32ビットビルド時の問題を修正するものです。具体的には、テストで使用される maxswap
の値が32ビット環境でオーバーフローを引き起こす可能性があったため、その値を修正しています。
コミット
commit 6d2d4ba94fb94dd5a9f581a1606d720bed8131dd
Author: Russ Cox <rsc@golang.org>
Date: Mon Jul 1 21:44:14 2013 -0400
sort: fix 32-bit build
TBR=golang-dev
CC=golang-dev
https://golang.org/cl/10856043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/6d2d4ba94fb94dd5a9f581a1606d720bed8131dd
元コミット内容
sort: fix 32-bit build
TBR=golang-dev
CC=golang-dev
https://golang.org/cl/10856043
変更の背景
このコミットの背景には、Go言語の sort
パッケージのテストコードが、32ビットアーキテクチャのシステムでビルドまたは実行された際に問題を引き起こす可能性があったという事実があります。具体的には、sort_test.go
内で定義されている maxswap
という変数の初期値が、32ビット符号付き整数の最大値を超える可能性のある表現 1 << 31
を使用していました。
32ビットシステムでは、符号付き整数(int
型など)の最大値は 2^31 - 1
(約21億) です。1 << 31
はビットシフト演算で 2^31
を意味します。これは、32ビット符号付き整数の表現可能な範囲のちょうど外側、つまり最上位ビットがセットされた状態になります。多くのプログラミング言語やシステムにおいて、この値は負の数として解釈されるか、あるいはオーバーフローエラーを引き起こす可能性があります。
Go言語の int
型は、実行環境のアーキテクチャに依存して32ビットまたは64ビットのいずれかになります。このため、64ビットシステムでは問題なく動作していたコードが、32ビットシステムでは予期せぬ挙動を示すことがありました。このコミットは、このようなクロスプラットフォーム互換性の問題を解消し、sort
パッケージのテストがすべてのサポートされるアーキテクチャで正しく動作するようにするためのものです。
前提知識の解説
1. ビットシフト演算子 (<<
)
A << B
は、数値 A
のビットを B
ビットだけ左にシフトする演算です。左シフトは、数値を 2^B
倍することに相当します。
例: 1 << 0
は 1
(2^0)
1 << 1
は 2
(2^1)
1 << 2
は 4
(2^2)
1 << 31
は 2^31
を意味します。
2. 符号付き整数とビット表現
コンピュータでは、整数は通常、固定されたビット数で表現されます。例えば、32ビット整数は32個のバイナリビットで構成されます。符号付き整数では、最上位ビット(一番左のビット)が数値の符号を表すために使用されます(0は正、1は負)。これにより、32ビット符号付き整数で表現できる値の範囲は、約 -2^31
から 2^31 - 1
までとなります。
- 32ビット符号付き整数の最大値:
2^31 - 1
(バイナリで0111...111
、1が31個続く) 2^31
の表現: バイナリで1000...000
(1の後に0が31個続く)。この値は、32ビット符号付き整数として解釈されると、通常は最小の負の数(-2^31)として扱われます。
3. Go言語の int
型
Go言語の int
型は、プラットフォームに依存する整数型です。
- 32ビットシステム(例:
GOARCH=386
)では、int
は32ビット幅です。 - 64ビットシステム(例:
GOARCH=amd64
)では、int
は64ビット幅です。
この特性により、1 << 31
のような定数式は、32ビットシステムではオーバーフローを引き起こす可能性がありますが、64ビットシステムでは問題なく 2^31
として扱われます。
4. sort
パッケージ
Go言語の sort
パッケージは、スライス(Goのスライスは動的配列のようなもの)をソートするための汎用的なインターフェースとアルゴリズムを提供します。sort.Interface
インターフェースを実装することで、任意のデータ型をソートできます。このコミットで変更された sort_test.go
は、このパッケージのソートアルゴリズムのテストを行うためのものです。
技術的詳細
問題の核心は、src/pkg/sort/sort_test.go
内の countOps
関数で maxswap
フィールドに値を設定する以下の行にありました。
maxswap: 1 << 31,
このコードは、maxswap
に 2^31
という値を設定しようとしています。
-
64ビットシステムの場合:
int
型は64ビット幅なので、1 << 31
は2^31
として正しく表現され、問題ありません。2^31
は64ビット符号付き整数の範囲内に収まります。 -
32ビットシステムの場合:
int
型は32ビット幅です。32ビット符号付き整数の最大値は2^31 - 1
です。1 << 31
は2^31
であり、これは32ビット符号付き整数の表現可能な最大値を超えています。この場合、Goコンパイラは通常、この定数式をint
型に変換しようとしますが、値がオーバーフローするため、結果として負の数(通常は-2^31
)として解釈されるか、コンパイルエラーを引き起こす可能性があります。テストコードの文脈では、maxswap
が負の値になることで、テストのロジックが意図しない挙動を示す可能性がありました。
この問題を解決するために、コミットでは maxswap
の値を以下のように変更しました。
maxswap: 1<<31 - 1,
この変更により、maxswap
の値は 2^31 - 1
となります。これは、32ビット符号付き整数の最大値と完全に一致します。これにより、32ビットシステムでもオーバーフローが発生せず、maxswap
が正しく最大の正の整数として設定されるようになります。
この修正は、テストコードの堅牢性を高め、Go言語がサポートするすべてのアーキテクチャで一貫したテスト結果を保証するために重要です。
コアとなるコードの変更箇所
変更は src/pkg/sort/sort_test.go
ファイルの1箇所のみです。
--- a/src/pkg/sort/sort_test.go
+++ b/src/pkg/sort/sort_test.go
@@ -504,7 +504,7 @@ func countOps(t *testing.T, algo func(Interface), name string) {
desc: name,
t: t,
data: make([]int, n),
- maxswap: 1 << 31,
+ maxswap: 1<<31 - 1,
}
for i := 0; i < n; i++ {
td.data[i] = rand.Intn(n / 5)
コアとなるコードの解説
変更された行は、countOps
関数内の匿名構造体の初期化部分です。
countOps
関数は、ソートアルゴリズムの操作回数をカウントするためのテストヘルパー関数です。この関数内で、testdata
構造体(td
)が初期化されます。testdata
構造体には maxswap
というフィールドがあり、これはソート中に許容される最大スワップ回数を表すものと推測されます。
元のコード:
maxswap: 1 << 31,
これは 2^31
を maxswap
に設定しようとしていました。32ビットシステムでは、この値は符号付き整数の範囲外であり、オーバーフローを引き起こす可能性がありました。
修正後のコード:
maxswap: 1<<31 - 1,
これは 2^31 - 1
を maxswap
に設定します。この値は、32ビット符号付き整数の最大値であり、すべてのGoがサポートするアーキテクチャで正しく表現できます。これにより、32ビットシステムでのビルドエラーや予期せぬテスト結果が回避されます。
この修正は、Go言語のクロスプラットフォーム互換性を維持し、異なるアーキテクチャ上でのテストの信頼性を確保するために不可欠でした。
関連リンク
- Go言語の
sort
パッケージのドキュメント: https://pkg.go.dev/sort - Go言語の
int
型に関するドキュメント: https://go.dev/ref/spec#Numeric_types
参考にした情報源リンク
- GitHubのコミットページ: https://github.com/golang/go/commit/6d2d4ba94fb94dd5a9f581a1606d720bed8131dd
- Go CL 10856043: https://golang.org/cl/10856043 (GoのコードレビューシステムGerritのリンク)
- Go言語の仕様書 (Numeric types): https://go.dev/ref/spec#Numeric_types
- ビットシフト演算子に関する一般的な情報 (例: Wikipediaなど)
- 符号付き整数表現に関する一般的な情報 (例: 2の補数表現など)