解決済み

SolarisとLinuxのグローバル変数の扱いについて

  • すぐに回答を!
  • 質問No.2083358
  • 閲覧数714
  • ありがとう数6
  • 気になる数0
  • 回答数4
  • コメント数0

お礼率 77% (190/244)

Solaris用のソースをLinuxで使えるように変更したいのですが、
グローバル変数について以下のようなことが発生していて困っています。
なにか、コンパイルオプションなどで対応はできないものでしょうか?

Solaris (CC)では
特にextern宣言しなくても同じシンボルの外部変数はコモンセグメントに1つだけ作成しコンパイル自体は正常である。

しかし、Linux (g++)では
externを宣言しないと同じシンボルを再定義したことになりエラーとなる。

これにより、グローバル変数を多用しているプログラムはLinuxでうまくコンパイルができない。
しかし、単純にextern宣言での対応は難しい。

extern宣言は外部で定義してあるグローバル変数を参照する
というものだがLinux では
1つの定義を意外は全てexternしなければ、2重定義エラーになってしまう。
つまり、実体が1つであとはそれを参照しているという形でなければいけない。
ところが、その実体をどこにするか特定することができない。

例えば、gというグローバル変数を仮定する。
A.c,B.c,C.cはその3つのソースよりAA.aという静的ライブラリを構成する。
gはA.cで定義してありB.c,C.cはそれを参照する。
ところが
C.cは個別にC.oというオブジェクトで他からの呼び出しがあり
別LMにリンクされる。
その時C.c内のgは実体を失うことになり未定義となる。
つまり、どれが実体になるかは何にリンクするかで決まるため
実態を特定できない。

また、共通のヘッダにグローバル変数が定義されている場合も、重複するというエラーを起こすため、
共通ヘッダからグローバル変数を分離し、何れかのソースにグローバル変数の実態を定義させる必要がある。
共通ヘッダを使っている他のソースはそのグローバル変数の実態を参照するようにexternの宣言をする。
通報する
  • 回答数4
  • 気になる
    質問をブックマークします。
    マイページでまとめて確認できます。

質問者が選んだベストアンサー

  • 回答No.4

ベストアンサー率 43% (30/69)

GCCの拡張機能 __attribute__ を使えば、外部変数をコモンセグメントに置くことができるらしいです。

// サンプル
#if defined(__GNUC__)
#define COMMON __attribute__((common))
#else
#define COMMON
#endif
int g COMMON;

まあ、あまりいい書き方ではないとは思うけど。
お礼コメント
ari_els

お礼率 77% (190/244)

この方法でやってみたところ、上手く行きました。
g++でも使えるみたいです。
とりあえず、この方法でやって行きたいと思います。

ありがとうございました。
投稿日時 - 2006-04-11 11:54:48
OKWAVE 20th Be MORE ありがとうをカタチに

その他の回答 (全3件)

  • 回答No.3

ベストアンサー率 23% (3656/15480)

もともと C では (C++ でも) 「複数の翻訳単位で同じ名前の外部定義を行う」ことは基本的に undefined behavior です.
なので, どういう形になっているのか明確でないのではっきりとは言えないのですが, もとのプログラムが (C/C++ の規格から見て) undefined behavior であり, Solaris のコンパイラである CC (あるいはリンカ?) の機能に依存している可能性も考えられます.
だいたい, 「C.c は個別に C.o というオブジェクトで他からの呼び出しがあり」という時点で構造がおかしい気がします. ライブラリを作ってるんだからそのライブラリをリンクするのが普通じゃないかなぁ?
お礼コメント
ari_els

お礼率 77% (190/244)

アドバイスありがとうございます。

ごもっともなご意見ですが、元々数社が共同で作った大きなシステム(それを全部引き取った。)だけにこの辺の整合性というか管理というかぼろぼろなんですよね。同じヘッダが数十個あるとか。同じソースでバージョンが違うものが同時に生きているとか、他人のオブジェクトを直接リンクしているとか、ソースが古いとかも。。。なので普通のことが行われていない部分が一杯あるんです。。。
投稿日時 - 2006-04-11 11:02:06
  • 回答No.2

ベストアンサー率 26% (31/117)

私が良く使う手ですと…

共通ヘッダとして、com.h を作成して、

<<<<< com.h >>>>>
#ifndef __MAIN_LOGIC
#define EXTERN extern
#endif

EXTERN int g;


<<<<< A.c >>>>>
#define __MAIN_LOGIC
#include "com.h"

<<<<< B.c >>>>>
#include "com.h"

<<<<< C.c >>>>>
#include "com.h"

このようにすると、いつでも同一のグローバル変数を参照するようになります。
注意点は、メインとなる1つのファイル(この場合はA.c)で、共通ファイルをインクルードする前に __MAIN_LOGIC という定義を宣言するということです。
他のサブとなるプログラムでは __MAIN_LOGIC の定義をしなければいいのです。

いかがでしょうか?
お礼コメント
ari_els

お礼率 77% (190/244)

回答ありがとうございます。
了解です。
やはりコンパイルオプションでは対応できないということですかね。
投稿日時 - 2006-04-11 10:45:04
  • 回答No.1

ベストアンサー率 44% (1423/3185)

ソースファイルがCで記述されているなら、g++ではなくてgccで処理してみては如何でしょうか。
手元のVine linux +gcc/g++ の処理系で試したところ、
gccを使えば、duplicated... のメッセージがでずに処理されるようです。
お礼コメント
ari_els

お礼率 77% (190/244)

アドバイスありがとうございます。

gccでは上手くいくことは、こちらでも調査済みですが、C++で書かれているソースもあるので、g++でコンパイルする必要があるのです。
投稿日時 - 2006-04-10 17:48:30
このQ&Aで解決しましたか?
AIエージェント「あい」

こんにちは。AIエージェントの「あい」です。
あなたの悩みに、OKWAVE 3,500万件のQ&Aを分析して最適な回答をご提案します。

関連するQ&A
こんな書き方もあるよ!この情報は知ってる?あなたの知識を教えて!
このQ&Aにはまだコメントがありません。
あなたの思ったこと、知っていることをここにコメントしてみましょう。

その他の関連するQ&A、テーマをキーワードで探す

キーワードでQ&A、テーマを検索する

特集


より良い社会へ。感謝経済プロジェクト始動

ピックアップ

ページ先頭へ