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

[インデックス 16675] ファイルの概要

このコミットは、Go言語のランタイムにおけるinclude/plan9/libc.hファイルにsize_t型を定義することで、ビルド時の問題を解決し、GCCの-Wconversion警告を回避することを目的としています。特に、Plan 9環境向けのコンパイルにおいて、標準ライブラリ関数(memcpyなど)の呼び出し時に発生する型変換警告に対処しています。

コミット

  • コミットハッシュ: e88478f1e0690878838bacf5159148ad872ec557
  • 作者: Ian Lance Taylor iant@golang.org
  • コミット日時: 2013年6月28日 金曜日 12:16:33 -0700
  • コミットメッセージ:
    include/plan9: define size_t to fix build breakage
    
    R=golang-dev, bradfitz
    CC=golang-dev
    https://golang.org/cl/10760043
    

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/e88478f1e0690878838bacf5159148ad872ec557

元コミット内容

include/plan9: define size_t to fix build breakage

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/10760043

変更の背景

このコミットの主な背景は、Go言語のランタイムがPlan 9環境でビルドされる際に発生していた問題と、GCCコンパイラが生成する-Wconversion警告です。

Go言語の初期の設計には、Bell Labsで開発されたオペレーティングシステムであるPlan 9の影響が強く見られます。Goのランタイムの一部は、Plan 9のシステムコールやライブラリの概念を模倣または利用していました。include/plan9/libc.hは、GoランタイムがPlan 9環境と連携するためのC言語ヘッダファイルであり、Plan 9の標準Cライブラリ関数や型定義をGoのビルドシステムに提供する役割を担っていました。

問題は、このヘッダファイルにsize_t型が定義されていなかったことに起因します。C言語の標準ライブラリ関数、特にメモリ操作を行うmemcpyのような関数は、サイズ引数としてsize_t型を期待します。size_tは、メモリ上のオブジェクトのサイズや配列のインデックスを表すために使用される符号なし整数型です。

size_tが明示的に定義されていない環境でこれらの標準ライブラリ関数を呼び出すと、コンパイラは引数の型が期待されるsize_tと異なる場合に、暗黙的な型変換を試みます。この暗黙的な型変換が、GCCの-Wconversion警告を引き起こしていました。-Wconversionは、データ損失や予期せぬ動作につながる可能性のある型変換(例えば、符号付き整数から符号なし整数への変換や、より大きな型から小さな型への変換)に対して警告を発するオプションです。

このような警告は、ビルドプロセスを中断させる「ビルドの破損 (build breakage)」とまではいかなくとも、コードの品質を低下させ、潜在的なバグを示唆するものでした。特に、Goのような厳格な型システムを持つ言語のランタイムにおいては、このような警告は極力排除されるべきです。

したがって、このコミットは、include/plan9/libc.hsize_tを明示的に定義することで、GCCの-Wconversion警告を解消し、Plan 9環境でのGoランタイムのビルドを安定させることを目的としています。

前提知識の解説

1. size_t

size_tは、C言語およびC++において、メモリ上のオブジェクトのサイズ(バイト単位)や、配列のインデックス、ループカウンタなどを表現するために使用される符号なし整数型です。stddef.h(C言語)またはcstddef(C++)ヘッダで定義されています。

  • 目的: size_tは、システムが表現できる最大オブジェクトサイズを保持できることが保証されています。これにより、異なるアーキテクチャやオペレーティングシステム間でコードの移植性を高めます。
  • 特性: 常に符号なし(非負)であり、通常はunsigned intunsigned long、またはunsigned long longのいずれかのエイリアスとして定義されます。具体的なサイズは、コンパイラとターゲットプラットフォームに依存します(例: 32ビットシステムでは32ビット、64ビットシステムでは64ビット)。
  • 使用例: malloccallocreallocmemcpystrlenなどの標準ライブラリ関数は、サイズや長さを表す引数にsize_tを使用します。

2. GCCの-Wconversion警告

GCC(GNU Compiler Collection)は、C、C++、Objective-C、Fortran、Ada、Goなどのプログラミング言語をサポートするコンパイラです。-Wconversionは、GCCのコンパイルオプションの一つで、暗黙的な型変換によってデータが失われたり、値の解釈が変わったりする可能性がある場合に警告を発します。

  • 警告の例:
    • 符号付き整数から符号なし整数への変換(負の値が大きな正の値になる)。
    • 浮動小数点数から整数への変換(小数点以下の切り捨て)。
    • より大きな型の整数からより小さな型の整数への変換(上位ビットの切り捨て)。
  • 重要性: この警告は、潜在的なバグや予期せぬ動作を防ぐために非常に重要です。開発者は、これらの警告を真剣に受け止め、意図しない型変換を明示的にキャストするか、適切な型を使用することで解消すべきです。

3. Plan 9

Plan 9 from Bell Labsは、ベル研究所の計算機科学研究センターで開発された分散オペレーティングシステムです。Unixの後継として設計され、その設計思想はGo言語にも大きな影響を与えています。

  • 特徴:
    • すべてがファイル: デバイス、ネットワーク接続、プロセスなど、システム内のすべてのリソースがファイルとして表現され、ファイルシステムを通じてアクセスされます。
    • 名前空間: 各プロセスは独自のファイルシステム名前空間を持ち、リソースの共有と分離を柔軟に行えます。
    • UTF-8: システム全体でUTF-8エンコーディングをネイティブにサポートしています。
  • Go言語との関連: Go言語の設計者の一部はPlan 9の開発者でもあり、Goのパッケージシステム、エラーハンドリング、並行処理モデル(goroutineとchannel)などにはPlan 9の思想が反映されています。Goの初期のビルドシステムやツールチェーンは、Plan 9のツール(例: 8g, 8l)に影響を受けていました。

4. memcpy関数

memcpyは、C言語の標準ライブラリ関数で、メモリブロックをコピーするために使用されます。string.hヘッダで宣言されています。

  • プロトタイプ: void *memcpy(void *dest, const void *src, size_t n);
  • 機能: srcが指すメモリ領域からnバイトをdestが指すメモリ領域にコピーします。
  • 注意点: destsrcのメモリ領域がオーバーラップしてはなりません。オーバーラップする場合にはmemmoveを使用します。
  • size_tとの関連: n引数はコピーするバイト数を表し、size_t型であると定義されています。これは、コピーされるデータ量が非常に大きくなる可能性があるため、符号なしの大きな値を扱える型が必要だからです。

技術的詳細

このコミットは、include/plan9/libc.hファイルにsize_t型をtypedef unsigned long size_t;として追加することで、Goランタイムのビルドプロセスにおける特定の警告と潜在的な問題を解決します。

GoランタイムがPlan 9環境でコンパイルされる際、内部的にC言語のコードが使用され、その中でmemcpyのような標準Cライブラリ関数が呼び出されることがあります。これらの関数は、引数としてsize_t型を期待しますが、include/plan9/libc.hにはこの型が定義されていませんでした。

C言語の標準では、size_tstddef.hで定義されることになっていますが、特定の環境やカスタムヘッダファイルでは、互換性や特定の要件のために独自の定義が必要になる場合があります。Plan 9の環境では、Goのビルドシステムが使用するlibc.hsize_tの定義を欠いていたため、コンパイラはmemcpyの第3引数(サイズ)に対して、例えばintlongのような別の整数型が渡された場合に、暗黙的な型変換を試みました。

この暗黙的な型変換は、GCCの-Wconversion警告を引き起こします。例えば、int型の変数をmemcpyのサイズ引数に渡した場合、intが符号付きであるのに対しsize_tは符号なしであるため、コンパイラは「符号付きから符号なしへの変換」という警告を発します。これは、負の値を渡した場合に予期せぬ大きな正の値として解釈される可能性があるため、潜在的なバグにつながります。

typedef unsigned long size_t;という定義を追加することで、以下の効果が得られます。

  1. -Wconversion警告の解消: memcpyなどの関数に渡されるサイズ引数が、期待されるsize_t型と一致するようになります。これにより、コンパイラは暗黙的な型変換を行う必要がなくなり、-Wconversion警告が抑制されます。これは、コードのクリーンさと品質を向上させます。
  2. ビルドの安定性向上: 警告が多すぎると、開発者は重要な警告を見落としがちになります。また、一部のビルドシステムやCI/CDパイプラインでは、警告をエラーとして扱い、ビルドを失敗させる設定になっている場合があります。この警告を解消することで、ビルドプロセスがより安定し、予期せぬビルドの失敗を防ぎます。
  3. 移植性の向上: size_tの定義を明示的に行うことで、GoランタイムがPlan 9環境でより標準的なC言語の慣習に従うようになり、将来的な互換性や移植性の問題を防ぐのに役立ちます。unsigned longが選ばれたのは、当時のPlan 9環境やGoのターゲットアーキテクチャにおいて、メモリサイズを表現するのに十分な幅を持ち、かつ一般的な選択肢であったためと考えられます。

この変更は、Goランタイムの低レベルな部分における細かな修正ですが、コンパイラの警告を排除し、ビルドの健全性を保つ上で重要な役割を果たします。

コアとなるコードの変更箇所

--- a/include/plan9/libc.h
+++ b/include/plan9/libc.h
@@ -22,3 +22,7 @@ void	flagfn0(char*, char*, void(*fn)(void));
 void	flagfn1(char*, char*, void(*fn)(char*));
 void	flagfn2(char*, char*, void(*fn)(char*, char*));
 void	flagprint(int);\n
+\n
+// The libraries use size_t to avoid -Wconversion warnings from GCC
+// when calling standard library functions like memcpy.
+typedef unsigned long size_t;

コアとなるコードの解説

変更はinclude/plan9/libc.hファイルに対して行われています。

  • 追加された行:
    // The libraries use size_t to avoid -Wconversion warnings from GCC
    // when calling standard library functions like memcpy.
    typedef unsigned long size_t;
    

このコードスニペットは、size_tという新しい型エイリアスを定義しています。

  • typedef: 既存の型に新しい名前(エイリアス)を付けるためのC言語のキーワードです。
  • unsigned long: 新しいエイリアスが参照する元の型です。これは符号なしの長整数型を意味します。size_tが符号なしであるのは、サイズやカウントが負になることはないためです。longは、システムが表現できる最大オブジェクトサイズを保持するのに十分な幅を持つように選ばれています。
  • size_t: unsigned long型の新しい名前です。

追加されたコメントは、この変更の意図を明確に説明しています。 「The libraries use size_t to avoid -Wconversion warnings from GCC when calling standard library functions like memcpy.」 これは、「ライブラリがsize_tを使用するのは、memcpyのような標準ライブラリ関数を呼び出す際にGCCの-Wconversion警告を避けるためである」という意味です。

この定義により、include/plan9/libc.hをインクルードするCコードは、size_t型を認識し、memcpyなどの関数に適切な型の引数を渡せるようになります。これにより、前述の-Wconversion警告が解消され、ビルドプロセスがよりクリーンになります。

関連リンク

  • Gerrit Change-Id: https://golang.org/cl/10760043 (GoプロジェクトのコードレビューシステムであるGerritへのリンク)

参考にした情報源リンク

[インデックス 16675] ファイルの概要

このコミットは、Go言語のランタイムにおけるinclude/plan9/libc.hファイルにsize_t型を定義することで、ビルド時の問題を解決し、GCCの-Wconversion警告を回避することを目的としています。特に、Plan 9環境向けのコンパイルにおいて、標準ライブラリ関数(memcpyなど)の呼び出し時に発生する型変換警告に対処しています。

コミット

  • コミットハッシュ: e88478f1e0690878838bacf5159148ad872ec557
  • 作者: Ian Lance Taylor iant@golang.org
  • コミット日時: 2013年6月28日 金曜日 12:16:33 -0700
  • コミットメッセージ:
    include/plan9: define size_t to fix build breakage
    
    R=golang-dev, bradfitz
    CC=golang-dev
    https://golang.org/cl/10760043
    

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/e88478f1e0690878838bacf5159148ad872ec557

元コミット内容

include/plan9: define size_t to fix build breakage

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/10760043

変更の背景

このコミットの主な背景は、Go言語のランタイムがPlan 9環境でビルドされる際に発生していた問題と、GCCコンパイラが生成する-Wconversion警告です。

Go言語の初期の設計には、Bell Labsで開発されたオペレーティングシステムであるPlan 9の影響が強く見られます。Goのランタイムの一部は、Plan 9のシステムコールやライブラリの概念を模倣または利用していました。include/plan9/libc.hは、GoランタイムがPlan 9環境と連携するためのC言語ヘッダファイルであり、Plan 9の標準Cライブラリ関数や型定義をGoのビルドシステムに提供する役割を担っていました。

問題は、このヘッダファイルにsize_t型が定義されていなかったことに起因します。C言語の標準ライブラリ関数、特にメモリ操作を行うmemcpyのような関数は、サイズ引数としてsize_t型を期待します。size_tは、メモリ上のオブジェクトのサイズや配列のインデックスを表すために使用される符号なし整数型です。

size_tが明示的に定義されていない環境でこれらの標準ライブラリ関数を呼び出すと、コンパイラは引数の型が期待されるsize_tと異なる場合に、暗黙的な型変換を試みます。この暗黙的な型変換が、GCCの-Wconversion警告を引き起こしていました。-Wconversionは、データ損失や予期せぬ動作につながる可能性のある型変換(例えば、符号付き整数から符号なし整数への変換や、より大きな型から小さな型への変換)に対して警告を発するオプションです。

このような警告は、ビルドプロセスを中断させる「ビルドの破損 (build breakage)」とまではいかなくとも、コードの品質を低下させ、潜在的なバグを示唆するものでした。特に、Goのような厳格な型システムを持つ言語のランタイムにおいては、このような警告は極力排除されるべきです。

したがって、このコミットは、include/plan9/libc.hsize_tを明示的に定義することで、GCCの-Wconversion警告を解消し、Plan 9環境でのGoランタイムのビルドを安定させることを目的としています。

前提知識の解説

1. size_t

size_tは、C言語およびC++において、メモリ上のオブジェクトのサイズ(バイト単位)や、配列のインデックス、ループカウンタなどを表現するために使用される符号なし整数型です。stddef.h(C言語)またはcstddef(C++)ヘッダで定義されています。

  • 目的: size_tは、システムが表現できる最大オブジェクトサイズを保持できることが保証されています。これにより、異なるアーキテクチャやオペレーティングシステム間でコードの移植性を高めます。
  • 特性: 常に符号なし(非負)であり、通常はunsigned intunsigned long、またはunsigned long longのいずれかのエイリアスとして定義されます。具体的なサイズは、コンパイラとターゲットプラットフォームに依存します(例: 32ビットシステムでは32ビット、64ビットシステムでは64ビット)。
  • 使用例: malloccallocreallocmemcpystrlenなどの標準ライブラリ関数は、サイズや長さを表す引数にsize_tを使用します。

2. GCCの-Wconversion警告

GCC(GNU Compiler Collection)は、C、C++、Objective-C、Fortran、Ada、Goなどのプログラミング言語をサポートするコンパイラです。-Wconversionは、GCCのコンパイルオプションの一つで、暗黙的な型変換によってデータが失われたり、値の解釈が変わったりする可能性がある場合に警告を発します。

  • 警告の例:
    • 符号付き整数から符号なし整数への変換(負の値が大きな正の値になる)。
    • 浮動小数点数から整数への変換(小数点以下の切り捨て)。
    • より大きな型の整数からより小さな型の整数への変換(上位ビットの切り捨て)。
  • 重要性: この警告は、潜在的なバグや予期せぬ動作を防ぐために非常に重要です。開発者は、これらの警告を真剣に受け止め、意図しない型変換を明示的にキャストするか、適切な型を使用することで解消すべきです。

3. Plan 9

Plan 9 from Bell Labsは、ベル研究所の計算機科学研究センターで開発された分散オペレーティングシステムです。Unixの後継として設計され、その設計思想はGo言語にも大きな影響を与えています。

  • 特徴:
    • すべてがファイル: デバイス、ネットワーク接続、プロセスなど、システム内のすべてのリソースがファイルとして表現され、ファイルシステムを通じてアクセスされます。
    • 名前空間: 各プロセスは独自のファイルシステム名前空間を持ち、リソースの共有と分離を柔軟に行えます。
    • UTF-8: システム全体でUTF-8エンコーディングをネイティブにサポートしています。
  • Go言語との関連: Go言語の設計者の一部はPlan 9の開発者でもあり、Goのパッケージシステム、エラーハンドリング、並行処理モデル(goroutineとchannel)などにはPlan 9の思想が反映されています。Goの初期のビルドシステムやツールチェーンは、Plan 9のツール(例: 8g, 8l)に影響を受けていました。

4. memcpy関数

memcpyは、C言語の標準ライブラリ関数で、メモリブロックをコピーするために使用されます。string.hヘッダで宣言されています。

  • プロトタイプ: void *memcpy(void *dest, const void *src, size_t n);
  • 機能: srcが指すメモリ領域からnバイトをdestが指すメモリ領域にコピーします。
  • 注意点: destsrcのメモリ領域がオーバーラップしてはなりません。オーバーラップする場合にはmemmoveを使用します。
  • size_tとの関連: n引数はコピーするバイト数を表し、size_t型であると定義されています。これは、コピーされるデータ量が非常に大きくなる可能性があるため、符号なしの大きな値を扱える型が必要だからです。

技術的詳細

このコミットは、include/plan9/libc.hファイルにsize_t型をtypedef unsigned long size_t;として追加することで、Goランタイムのビルドプロセスにおける特定の警告と潜在的な問題を解決します。

GoランタイムがPlan 9環境でコンパイルされる際、内部的にC言語のコードが使用され、その中でmemcpyのような標準Cライブラリ関数が呼び出されることがあります。これらの関数は、引数としてsize_t型を期待しますが、include/plan9/libc.hにはこの型が定義されていませんでした。

C言語の標準では、size_tstddef.hで定義されることになっていますが、特定の環境やカスタムヘッダファイルでは、互換性や特定の要件のために独自の定義が必要になる場合があります。Plan 9の環境では、Goのビルドシステムが使用するlibc.hsize_tの定義を欠いていたため、コンパイラはmemcpyの第3引数(サイズ)に対して、例えばintlongのような別の整数型が渡された場合に、暗黙的な型変換を試みました。

この暗黙的な型変換は、GCCの-Wconversion警告を引き起こします。例えば、int型の変数をmemcpyのサイズ引数に渡した場合、intが符号付きであるのに対しsize_tは符号なしであるため、コンパイラは「符号付きから符号なしへの変換」という警告を発します。これは、負の値を渡した場合に予期せぬ大きな正の値として解釈される可能性があるため、潜在的なバグにつながります。

typedef unsigned long size_t;という定義を追加することで、以下の効果が得られます。

  1. -Wconversion警告の解消: memcpyなどの関数に渡されるサイズ引数が、期待されるsize_t型と一致するようになります。これにより、コンパイラは暗黙的な型変換を行う必要がなくなり、-Wconversion警告が抑制されます。これは、コードのクリーンさと品質を向上させます。
  2. ビルドの安定性向上: 警告が多すぎると、開発者は重要な警告を見落としがちになります。また、一部のビルドシステムやCI/CDパイプラインでは、警告をエラーとして扱い、ビルドを失敗させる設定になっている場合があります。この警告を解消することで、ビルドプロセスがより安定し、予期せぬビルドの失敗を防ぎます。
  3. 移植性の向上: size_tの定義を明示的に行うことで、GoランタイムがPlan 9環境でより標準的なC言語の慣習に従うようになり、将来的な互換性や移植性の問題を防ぐのに役立ちます。unsigned longが選ばれたのは、当時のPlan 9環境やGoのターゲットアーキテクチャにおいて、メモリサイズを表現するのに十分な幅を持ち、かつ一般的な選択肢であったためと考えられます。

この変更は、Goランタイムの低レベルな部分における細かな修正ですが、コンパイラの警告を排除し、ビルドの健全性を保つ上で重要な役割を果たします。

コアとなるコードの変更箇所

--- a/include/plan9/libc.h
+++ b/include/plan9/libc.h
@@ -22,3 +22,7 @@ void	flagfn0(char*, char*, void(*fn)(void));
 void	flagfn1(char*, char*, void(*fn)(char*));
 void	flagfn2(char*, char*, void(*fn)(char*, char*));
 void	flagprint(int);\n
+\n
+// The libraries use size_t to avoid -Wconversion warnings from GCC
+// when calling standard library functions like memcpy.
+typedef unsigned long size_t;

コアとなるコードの解説

変更はinclude/plan9/libc.hファイルに対して行われています。

  • 追加された行:
    // The libraries use size_t to avoid -Wconversion warnings from GCC
    // when calling standard library functions like memcpy.
    typedef unsigned long size_t;
    

このコードスニペットは、size_tという新しい型エイリアスを定義しています。

  • typedef: 既存の型に新しい名前(エイリアス)を付けるためのC言語のキーワードです。
  • unsigned long: 新しいエイリアスが参照する元の型です。これは符号なしの長整数型を意味します。size_tが符号なしであるのは、サイズやカウントが負になることはないためです。longは、システムが表現できる最大オブジェクトサイズを保持するのに十分な幅を持つように選ばれています。
  • size_t: unsigned long型の新しい名前です。

追加されたコメントは、この変更の意図を明確に説明しています。 「The libraries use size_t to avoid -Wconversion warnings from GCC when calling standard library functions like memcpy.」 これは、「ライブラリがsize_tを使用するのは、memcpyのような標準ライブラリ関数を呼び出す際にGCCの-Wconversion警告を避けるためである」という意味です。

この定義により、include/plan9/libc.hをインクルードするCコードは、size_t型を認識し、memcpyなどの関数に適切な型の引数を渡せるようになります。これにより、前述の-Wconversion警告が解消され、ビルドプロセスがよりクリーンになります。

関連リンク

  • Gerrit Change-Id: https://golang.org/cl/10760043 (GoプロジェクトのコードレビューシステムであるGerritへのリンク)

参考にした情報源リンク