Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 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言語はfloat32float64のみを標準の浮動小数点数型としてサポートすることになります。

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, int81
    uint16, int162
    uint32, int32, float324
    uint64, int64, float648
  • 最小アライメントプロパティの保証:

    1. 任意の型の変数xについて: 1 <= unsafe.Alignof(x) <= unsafe.Maxalign
    2. 算術型の変数xについて: unsafe.Alignof(x)は、unsafe.Sizeof(x)unsafe.Maxalignの小さい方であり、かつ少なくとも1です。
    3. 構造体型の変数xについて: unsafe.Alignof(x)は、xの各フィールドfに対するunsafe.Alignof(x.f)のすべての値の中で最大のものであり、かつ少なくとも1です。
    4. 配列型の変数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パッケージとメモリのアライメントに関する重要なドキュメントを追加しています。

  1. 日付の更新: 仕様書の更新日を2009年2月6日から2月11日に変更しています。これは、このコミットがGo言語の初期開発段階における継続的な仕様の進化の一部であることを示しています。

  2. 目次の追加: Systems considerationsという新しいトップレベルのセクションが導入され、その下にPackage unsafeSize and alignment guaranteesというサブセクションが追加されました。これにより、Go言語が低レベルのシステムプログラミングとメモリレイアウトをどのように扱うかについての公式なガイダンスが提供されます。

  3. float80の削除: float80型がGoの基本型およびプラットフォーム非依存の数値型から削除されました。これは、Goがよりポータブルで、広くサポートされているfloat32float64に焦点を当てるという設計上の決定を反映しています。これにより、Goの数値型システムが簡素化され、異なるアーキテクチャ間での一貫性が向上します。

  4. Package unsafeセクションの追加:

    • このセクションでは、unsafeパッケージがGoの型システムをバイパスするための低レベル機能を提供することを明確にしています。これは、C言語との相互運用や、特定のパフォーマンス要件を持つコードなど、特殊なケースでのみ使用されるべきであり、手動での型安全性検証が必要であることが強調されています。
    • unsafeパッケージが提供する主要な要素(Maxalign定数、Pointer型、AlignofOffsetofSizeof関数)が定義されています。これらの関数は、それぞれメモリ上のサイズ、構造体フィールドのオフセット、およびアライメント情報を取得するために使用されます。
    • unsafe.Pointerが任意のポインタ型とuintptrの間で変換可能であること、およびその使用例が示されています。これは、Goの厳格な型システムを一時的に迂回して、生のメモリアドレスを操作するための主要なメカニズムです。
    • メモリのアライメントの概念が説明され、Alignof関数がどのようにアライメント要件を返すかが示されています。これは、特定のハードウェア要件を満たすために重要です。
  5. Size and alignment guaranteesセクションの追加:

    • このセクションでは、Goコンパイラが保証する算術型の具体的なサイズ(バイト単位)が表形式で示されています。これにより、開発者はGoプログラムが異なるプラットフォームでどのようにメモリを消費するかを予測できます。
    • Goコンパイラが保証する最小アライメントプロパティが詳細にリストされています。これには、任意の型、算術型、構造体型、配列型のアライメントに関するルールが含まれます。これらの保証は、データ構造のパディングとメモリレイアウトを理解し、クロスプラットフォームでの互換性とパフォーマンスを確保するために不可欠です。

これらの変更は、Go言語が単なる高レベル言語ではなく、必要に応じて低レベルのメモリ操作とシステムプログラミングをサポートする能力を持つことを公式に認めるものです。同時に、unsafeパッケージの使用には注意が必要であるという警告も含まれており、Goの設計哲学である「安全性とシンプルさ」を維持しようとする姿勢がうかがえます。

関連リンク

参考にした情報源リンク