[インデックス 1662] ファイルの概要
このコミットは、Go言語の仕様書(doc/go_spec.txt
)にunsafe
パッケージに関する新しいセクションと、型のアライメント保証に関する詳細を追加するものです。また、float80
型が仕様から削除されています。
コミット
commit 52c02c2d5d8fd4078ad76d12e60913d2a536238a
Author: Robert Griesemer <gri@golang.org>
Date: Wed Feb 11 13:46:30 2009 -0800
Added section on package unsafe:
- contains a (proposed) constant Maxalign
- contains some text re" alignment guarantees
R=ken,r
DELTA=97 (94 added, 1 deleted, 2 changed)
OCL=24791
CL=24871
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/52c02c2d5d8fd4078ad76d12e60913d2a536238a
元コミット内容
Go言語の仕様書にunsafe
パッケージに関するセクションを追加し、提案されている定数Maxalign
とアライメント保証に関する記述を含める。
変更の背景
Go言語は、高レベルな抽象化を提供しつつも、システムプログラミングの領域にも対応できる設計を目指しています。そのため、メモリの直接操作や型システムを迂回するような低レベルな操作が必要となる場合があります。unsafe
パッケージは、このような特定のユースケース(例えば、C言語との相互運用、高性能なデータ構造の実装、特定のハードウェアとのインタフェースなど)に対応するために導入されました。
このコミットは、unsafe
パッケージの存在とその機能、特にメモリのアライメントに関する保証を公式な仕様書に明記することで、Go言語の低レベルプログラミング能力を明確にし、開発者が安全かつ予測可能な方法でこれらの機能を利用できるようにするためのものです。また、float80
型の削除は、Go言語がサポートする浮動小数点数の標準をIEEE-754 32ビットおよび64ビットに限定し、プラットフォーム間の互換性とシンプルさを追求する設計思想を反映しています。
前提知識の解説
1. メモリのアライメント (Memory Alignment)
コンピュータのプロセッサは、メモリからデータを読み書きする際に、特定のメモリアドレスにデータが配置されていることを要求する場合があります。これを「メモリのアライメント」と呼びます。例えば、4バイトの整数は4の倍数のアドレスに配置される必要がある、といった制約です。
- アライメントの理由:
- パフォーマンス: プロセッサは、アライメントされたデータにアクセスする方が高速に動作します。アライメントされていないデータへのアクセスは、複数のメモリアクセスを必要としたり、特別なハードウェア処理を伴ったりするため、性能が低下する可能性があります。
- ハードウェアの制約: 一部のプロセッサは、アライメントされていないデータへのアクセスを許可せず、ハードウェア例外(アライメントフォルト)を発生させることがあります。
- パディング (Padding): 構造体(struct)のメンバがアライメント要件を満たすように、コンパイラはメンバ間に未使用のバイト(パディング)を挿入することがあります。これにより、構造体のサイズが個々のメンバのサイズの合計よりも大きくなることがあります。
2. unsafe
パッケージ
Go言語のunsafe
パッケージは、Goの型システムが通常強制する安全規則を意図的にバイパスするための機能を提供します。このパッケージを使用すると、ポインタの算術演算や、異なる型間のポインタ変換など、低レベルなメモリ操作が可能になります。
- なぜ「unsafe」なのか:
unsafe
パッケージを使用すると、Goのメモリ安全性の保証が損なわれる可能性があります。誤用すると、プログラムのクラッシュ、データ破損、セキュリティ脆弱性につながるため、使用には細心の注意と深い理解が必要です。 - 主な機能:
unsafe.Pointer
: 任意のGoのポインタ型とuintptr
型との間で相互変換が可能な特殊なポインタ型。これにより、型システムを無視したポインタ操作が可能になります。unsafe.Sizeof
: 変数や型のメモリ上のサイズをバイト単位で返します。unsafe.Offsetof
: 構造体のフィールドが、その構造体の先頭から何バイト目に位置するかを返します。unsafe.Alignof
: 変数や型のアライメント要件をバイト単位で返します。
3. float80
型
float80
は、IEEE 754標準で定義されている80ビット浮動小数点数型です。これは主にIntel x87 FPU(浮動小数点演算ユニット)で内部的に使用される拡張精度形式です。Go言語の初期の仕様には含まれていましたが、このコミットで削除されました。これは、Goがよりポータブルで、広くサポートされているIEEE 754の32ビット(float32
)と64ビット(float64
)の浮動小数点数に焦点を当てるという設計上の決定を反映しています。
技術的詳細
このコミットは、Go言語の仕様書に以下の重要な変更を加えています。
1. doc/go_spec.txt
の更新日付の変更
仕様書の冒頭の日付が「(February 6, 2009)」から「(February 11, 2009)」に更新されました。これは、このコミットが適用された日付を反映しています。
2. 目次への新しいセクションの追加
目次に以下の新しいエントリが追加されました。
Systems considerations
Package unsafe
Size and alignment guarantees
これにより、unsafe
パッケージとメモリのアライメントに関する情報が、Go言語の公式仕様の一部として明確に位置づけられました。
3. float80
型の削除
float80
型が、Goの組み込み型およびプラットフォーム非依存の数値型の一覧から削除されました。これにより、Go言語はfloat32
とfloat64
のみを標準の浮動小数点数型としてサポートすることになります。
4. Systems considerations
セクションの追加
このセクションは、Go言語がシステムレベルのプログラミングをどのように扱うかについての概要を提供します。
Package unsafe
セクションの詳細
このセクションでは、unsafe
パッケージの目的と提供される機能について詳しく説明しています。
-
目的:
unsafe
パッケージは、コンパイラに認識されている特別なパッケージであり、Goの型システムに違反する操作を含む低レベルプログラミングのための機能を提供します。このパッケージを使用するコードは、型安全性のために手動で検証される必要があります。 -
パッケージインターフェース:
unsafe
パッケージは、少なくとも以下のインターフェースを提供します。package unsafe const Maxalign type Pointer *any func Alignof(variable any) int func Offsetof(selector any) int func Sizeof(variable any) int
any
は任意のGoの型を表す擬似型であり、通常のGoプログラムでは利用できません。unsafe.Pointer
: 任意のポインタ型、およびuintptr
型の値は、unsafe.Pointer
に相互変換できます。これにより、型チェックをバイパスしたポインタ操作が可能になります。Sizeof(variable any) int
: 任意の型の変数のサイズをバイト単位で返します。Offsetof(selector any) int
: 構造体のフィールドセレクタを取り、そのフィールドが構造体のアドレスから何バイト目に位置するかを返します。以下の条件が満たされます。uintptr(unsafe.Pointer(&s)) + uintptr(unsafe.Offsetof(s.f)) == uintptr(unsafe.Pointer(&s.f))
Alignof(variable any) int
: 任意の型の変数のアライメントをバイト単位で返します。以下の条件が満たされます。uintptr(unsafe.Pointer(&x)) % uintptr(unsafe.Alignof(x)) == 0
Maxalign
: 最大のアライメント値を示す定数です。通常、最大の算術型(float64
の場合は8)のunsafe.Sizeof(x)
の値に対応しますが、アライメント制約が緩いシステムやスペースが制約されているシステムでは小さくなる可能性があります。
Size and alignment guarantees
セクションの詳細
このセクションでは、Goコンパイラが保証する型ごとのサイズと最小アライメントプロパティについて説明しています。
-
算術型のサイズ保証:
型 サイズ(バイト) byte
,uint8
,int8
1 uint16
,int16
2 uint32
,int32
,float32
4 uint64
,int64
,float64
8 -
最小アライメントプロパティの保証:
- 任意の型の変数
x
について:1 <= unsafe.Alignof(x) <= unsafe.Maxalign
- 算術型の変数
x
について:unsafe.Alignof(x)
は、unsafe.Sizeof(x)
とunsafe.Maxalign
の小さい方であり、かつ少なくとも1です。 - 構造体型の変数
x
について:unsafe.Alignof(x)
は、x
の各フィールドf
に対するunsafe.Alignof(x.f)
のすべての値の中で最大のものであり、かつ少なくとも1です。 - 配列型の変数
x
について:unsafe.Alignof(x)
は、unsafe.Alignof(x[0])
と同じであり、かつ少なくとも1です。
- 任意の型の変数
これらの保証は、Goプログラムが異なるアーキテクチャやコンパイラで一貫したメモリレイアウトとパフォーマンスを持つことを保証するために重要です。
コアとなるコードの変更箇所
このコミットの主要な変更は、doc/go_spec.txt
ファイルに対するものです。
--- a/doc/go_spec.txt
+++ b/doc/go_spec.txt
@@ -3,7 +3,7 @@ The Go Programming Language Specification (DRAFT)
Robert Griesemer, Rob Pike, Ken Thompson
-(February 6, 2009)
+(February 11, 2009)
----
@@ -254,6 +254,10 @@ Contents
Program initialization and execution
+ Systems considerations
+ Package unsafe
+ Size and alignment guarantees
+
----
@@ -753,7 +757,7 @@ The following identifiers are predeclared:
All basic types:
bool, byte, uint8, uint16, uint32, uint64, int8, int16, int32, int64,
- float32, float64, float80, string
+ float32, float64, string
A set of platform-specific convenience types:
@@ -1102,7 +1106,6 @@ The following list enumerates all platform-independent numeric types:
float32 the set of all valid IEEE-754 32-bit floating point numbers
float64 the set of all valid IEEE-754 64-bit floating point numbers
-- float80 the set of all valid IEEE-754 80-bit floating point numbers
Integer types are represented in the usual binary format; the value of
an n-bit integer is n bits wide. A negative signed integer is represented
@@ -3453,3 +3456,93 @@ Program execution begins by initializing the main package and then
invoking main.main().
When main.main() returns, the program exits.
+
+
+----
+
+Systems considerations
+----
+
+Package unsafe
+----
+
+The special package "unsafe", known to the compiler, provides facilities
+for low-level programming including operations that violate the Go type
+system. A package using "unsafe" must be vetted manually for type safety.
+
+The package "unsafe" provides (at least) the following package interface:
+
+ package unsafe
+
+ const Maxalign
+
+ type Pointer *any
+
+ func Alignof(variable any) int
+ func Offsetof(selector any) int
+ func Sizeof(variable any) int
+
+The pseudo type "any" stands for any Go type; "any" is not a type generally
+available in Go programs.
+
+Any pointer type as well as values of type "uintptr" can be converted into
+an "unsafe.Pointer" and vice versa.
+
+The function "Sizeof" takes an expression denoting a variable of any type
+and returns the size of the variable in bytes.
+
+The function "Offsetof" takes a selector (§Selectors) denoting a struct
+field of any type and returns the field offset in bytes relative to the
+struct address. Specifically, the following condition is satisfied for
+a struct "s" with field "f":
+
+ uintptr(unsafe.Pointer(&s)) + uintptr(unsafe.Offsetof(s.f)) ==
+ uintptr(unsafe.Pointer(&s.f))
+
+Computer architectures may impose restrictions on the memory addresses accessed
+directly by machine instructions. A common such restriction is the requirement
+for such addresses to be ``aligned''; that is, addresses must be a multiple
+of a factor, the ``alignment''. The alignment depends on the type of datum
+accessed.
+
+The function "Alignof" takes an expression denoting a variable of any type
+and returns the alignment of the variable in bytes. The following alignment
+condition is satisfied for a variable "x":
+
+ uintptr(unsafe.Pointer(&x)) % uintptr(unsafe.Alignof(x)) == 0
+
+The maximum alignment is given by the constant "unsafe.Maxalign".
+It usually corresponds to the value of "unsafe.Sizeof(x)" for
+a variable "x" of the largest arithmetic type (8 for a float64), but may
+be smaller on systems that have less stringent alignment restrictions
+or are space constrained.
+
+
+Size and alignment guarantees
+----
+
+For the arithmetic types (§Arithmetic types), a Go compiler guarantees the
+following sizes:
+
+ type size in bytes
+
+ byte, uint8, int8 1
+ uint16, int16 2
+ uint32, int32, float32 4
+ uint64, int64, float64 8
+
+A Go compiler guarantees the following minimal alignment properties:
+
+1) For a variable "x" of any type: "1 <= unsafe.Alignof(x) <= unsafe.Maxalign".
+
+2) For a variable "x" of arithmetic type: "unsafe.Alignof(x)" is the smaller
+ of "unsafe.Sizeof(x)" and "unsafe.Maxalign", but at least 1.
+
+3) For a variable "x" of struct type: "unsafe.Alignof(x)" is the largest of
+ all the values "unsafe.Alignof(x.f)" for each field "f" of x, but at least 1.
+
+4) For a variable "x" of array type: "unsafe.Alignof(x)" is the same as
+ unsafe.Alignof(x[0]), but at least 1.
コアとなるコードの解説
このコミットは、Go言語の仕様書にunsafe
パッケージとメモリのアライメントに関する重要なドキュメントを追加しています。
-
日付の更新: 仕様書の更新日を2009年2月6日から2月11日に変更しています。これは、このコミットがGo言語の初期開発段階における継続的な仕様の進化の一部であることを示しています。
-
目次の追加:
Systems considerations
という新しいトップレベルのセクションが導入され、その下にPackage unsafe
とSize and alignment guarantees
というサブセクションが追加されました。これにより、Go言語が低レベルのシステムプログラミングとメモリレイアウトをどのように扱うかについての公式なガイダンスが提供されます。 -
float80
の削除:float80
型がGoの基本型およびプラットフォーム非依存の数値型から削除されました。これは、Goがよりポータブルで、広くサポートされているfloat32
とfloat64
に焦点を当てるという設計上の決定を反映しています。これにより、Goの数値型システムが簡素化され、異なるアーキテクチャ間での一貫性が向上します。 -
Package unsafe
セクションの追加:- このセクションでは、
unsafe
パッケージがGoの型システムをバイパスするための低レベル機能を提供することを明確にしています。これは、C言語との相互運用や、特定のパフォーマンス要件を持つコードなど、特殊なケースでのみ使用されるべきであり、手動での型安全性検証が必要であることが強調されています。 unsafe
パッケージが提供する主要な要素(Maxalign
定数、Pointer
型、Alignof
、Offsetof
、Sizeof
関数)が定義されています。これらの関数は、それぞれメモリ上のサイズ、構造体フィールドのオフセット、およびアライメント情報を取得するために使用されます。unsafe.Pointer
が任意のポインタ型とuintptr
の間で変換可能であること、およびその使用例が示されています。これは、Goの厳格な型システムを一時的に迂回して、生のメモリアドレスを操作するための主要なメカニズムです。- メモリのアライメントの概念が説明され、
Alignof
関数がどのようにアライメント要件を返すかが示されています。これは、特定のハードウェア要件を満たすために重要です。
- このセクションでは、
-
Size and alignment guarantees
セクションの追加:- このセクションでは、Goコンパイラが保証する算術型の具体的なサイズ(バイト単位)が表形式で示されています。これにより、開発者はGoプログラムが異なるプラットフォームでどのようにメモリを消費するかを予測できます。
- Goコンパイラが保証する最小アライメントプロパティが詳細にリストされています。これには、任意の型、算術型、構造体型、配列型のアライメントに関するルールが含まれます。これらの保証は、データ構造のパディングとメモリレイアウトを理解し、クロスプラットフォームでの互換性とパフォーマンスを確保するために不可欠です。
これらの変更は、Go言語が単なる高レベル言語ではなく、必要に応じて低レベルのメモリ操作とシステムプログラミングをサポートする能力を持つことを公式に認めるものです。同時に、unsafe
パッケージの使用には注意が必要であるという警告も含まれており、Goの設計哲学である「安全性とシンプルさ」を維持しようとする姿勢がうかがえます。
関連リンク
- Go言語の公式ウェブサイト
- Go言語のドキュメント
- Go言語の仕様書 (現在のバージョン) - このコミットが変更した当時の仕様書とは異なる可能性があります。