[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
この節では、GNU C や GNU C++ を、特定のシステム上の 他のコンパイラや、アセンブラ、リンカ、ライブラリ、デバッグと共に 使う場合に出会う様々な問題を説明する。
これは、意図的にそうしているのである。より深刻な問題を回避するために。 C++ の実装は、コンパイラにより、内部の詳細が色々異なっている。 例えば、クラスのインスタンスの配置方法、多重継承の実装方法、それに 仮想関数の呼びだし方法などが異なっている。もし名前のエンコード方法に 同じにすると、他のコンパイラでコンパイルされたライブラリをリンクできて しまうことになる。しかし、実装方法の異なるものをリンクしたことにより、 そのプログラムは実行すると異常を起こすだろう。 名前のエンコード方法を異なるものにしておけば、互換性のないライブラリを リンクすることを、プログラムの実行時ではなく、リンク時に検出できるのである。
多くのシステムでは、ヘッダファイルは、fixincludes
で
修正しないと GCC では使えない。修正されたヘッダファイルは
新規のディレクトリに置かれる。GCC は、‘/usr/include’ の
前にこのディレクトリを検索する。
オプション ‘-I/usr/include’ を指定すると、GCC は、
まず、正しいヘッダの前に、‘/usr/include’ を検索する。
その結果は、正しくないヘッダファイルを使うことになる。
その場合正しくは以下のようにする(ただし、C プログラムをコンパイルする場合)。
-I/usr/local/lib/gcc-lib/target/version/include -I/usr/include |
C++ のプログラムについては、GCC はさらに、標準 C サブルーチンへの C++ インターフェースを定義する特別なディレクトリを検索する。 このディレクトリは、他の標準インクルードディレクトリの前にに 検索することを意図しているので、他に優先する。 C++ のプログラムをコンパイルするときにインクルードディレクトリを 明示的に指定する場合には、次のオプションをまず指定し、その後に上記の 二つのオプションを指定する。
-I/usr/local/lib/g++-include |
double
型の値を全て8バイト境界に
揃える。そしてあらゆる double
がそのように揃っていることを
想定している。Sun のコンパイラも通常は double
の値を
8バイトのアラインメントにするが、一つだけ例外がある。double
型の
関数の引数はアラインメントがとられないことがある。
その結果、Sun CC でコンパイルした関数が double
型の引数の
アドレスを取り、この double *
型のポインタを GCC でコンパイル
した関数に渡すと、そのポインタを間接参照すると致命的なシグナルを
受けることになるだろう。
これを解決する方法の一つは、プログラム全体を GCC で
コンパイルすることである。もう一つの解決方法は、Sun CC でコンパイルする
関数を修正して、引数をローカル変数にコピーするようにすることである。
ローカル変数は常に正しく整合境界が取られる。
三番目の方法としては、ポインタを使って間接参照を行なっている
関数を修正して、‘*’ を使って直接的に参照する代わりに、
以下の関数 access_double
を使うことである。
inline double access_double (double *unaligned_ptr) { union d2i { double d; int i[2]; }; union d2i *p = (union d2i *) unaligned_ptr; union d2i u; u.i[0] = p->i[0]; u.i[1] = p->i[1]; return u.d; } |
ポインタへの格納も同じ共用体を使って同様に行なうことができる。
malloc
関数が
確保するメモリのアラインメントが 4 バイトにしかなっていない。
SPARC 用の GCC は、double 型は 8 バイトアラインメントであることを
想定しているので、この結果、double の値を ‘libmalloc.a’ ライブラリで
確保ししたメモリに格納すると、致命的なシグナルを受ける。
解決するには、‘libmalloc.a’ ライブラリを使わないことである。
代わりに、‘libc.a’ にある malloc
やその関連関数を
使えば良い。‘libc.a’ にあるものには、この問題はない。
_dlclose
、_dlsym
、_dlopen
といった
未定義シンボルが出たら、MIT 版の X Window System から
‘mit/util/misc/dlsym.c’ を取ってきてリンクすると良い。
cc
は
GCC を正しくコンパイルしない。理由はまだわからない。
ただし、以前のバージョンの HP-UX でコンパイルした GCC は HP-UX 9.01 上で
正しく動作するので、9.01 で GCC をコンパイルするのに使える。
alloca
や可変長配列を使っている
関数の場合にうまくいかない。これは、GCC がそういう関数に対しては
HP-UX のスタック巻き上げ記述子を生成しないからである。これを生成するのは
不可能にさえ思える。
(warning) Use of GR3 when frame >= 8192 may cause conflict. |
この警告は無害なので無視して大丈夫である。
IBM は修正済みのアセンブラを出している。ただし、残念なことに このアップグレードしたアセンブラは、AIX 3.2 の PTF リリース(3.2.2、 3.2.3、3.2.3e)のどれにも含まれていなかった。 AIX3.1 のユーザは PTF U403044 を、AIX3.2 のユーザは PTF U416277 を IBM に要求すること。これらの更新についての詳しい情報は ‘README.RS6000’ というファイルを参照のこと。
修正済みのアセンブラがあるかどうかは以下のコマンドでテストできる。
as -u < /dev/null |
このコマンドが正常に終了すれば、修正済みアセンブラがインストール済みである。 "-u" というオプションは知らないよと出たら、修正版を注文する必要がある。
extern int foo; … foo … static int foo; |
という形のコードをコンパイルすると、リンカが foo
が
未定義シンボルであると言ってくる。これは他の多くのシステムとは
異なる動作であるが、これはバグではない。extern
変数を
static
として再定義することは、ANSI C では未定義であるからである。
size_t
の typedef が二つあるというエラー
メッセージが出る。‘sys/types.h’ を
編集して、size_t
の定義の前後に以下のような行を加える必要がある。
#ifndef _SIZE_T #define _SIZE_T 実際の typedef をここに置く #endif |
GCC は、Ultrix の C コンパイラと同じ方の規約を使っている。 以下のオプションを使うと、Fortran コンパイラと互換性のあるコードを 生成可能である。
-fcall-saved-r2 -fcall-saved-r3 -fcall-saved-r4 -fcall-saved-r5 |
-L/usr/local/lib/gcc-lib/we32k-att-sysv/2.8.1 -lgcc -lc_s |
最初に、‘-lgcc’ オプションで指定されるライブラリ ‘libgcc.a’ を 探す場所を指定する。
GCC は、ちょうど cc
が行なうのと同じように、
ld
を起動することでリンクを行なっているので、ld
を
起動するのにどのコンパイルプログラムを使うかが関係してくる理由は
ない。誰かがこの問題の原因を突き止めれば、修正するのはおそらく
簡単だろう。
ecvt
、
fcvt
、gcvt
のバグのためである。
これらの関数は、有効な浮動小数点数を指定しても、‘NaN’ を
表示するときがある。
あるいは、GCC 自身をコンパイルするときは ‘-noasmopt’ オプションを 指定し、読者自身のプログラムをコンパイルするときも同様にする方法が ある。(これは、Irix のアセンブラの最適化をしないようにする一時的な 小細工である。) この方法が読者にとって必要であることが判ったなら、 ‘specs’ ファイルのアセンブラ指定を書き換えて、無条件に ‘-O0’ をアセンブラに渡すようにし、‘-O2’ や ‘-O3’ は 絶対渡らないようにするのである。
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated
using texi2html 1.78.