17

重複の可能性:
定数変数がヘッダーで機能しない

共有オブジェクトの作成に使用するヘッダーファイルには、次のものがあります。

#ifndef LIB_HECA_DEF_H_
#define LIB_HECA_DEF_H_

struct dsm_config {
    int auto_unmap;
    int enable_copy_on_access;
};

enum { NO_AUTO_UNMAP, AUTO_UNMAP } unmap_flag;
enum { NO_ENABLE_COA, ENABLE_COA } coa_flag;

const struct dsm_config DEFAULT_DSM_CONFIG = { AUTO_UNMAP, NO_ENABLE_COA };

<more code ...>

#endif

コンパイルすると、次のエラーが発生します。

cc -g -Wall -pthread libheca.c dsm_init.c -DDEBUG    master.c   -o master
/tmp/cciBnGer.o:(.rodata+0x0): multiple definition of `DEFAULT_DSM_CONFIG'
/tmp/cckveWVO.o:(.rodata+0x0): first defined here
collect2: ld returned 1 exit status
make: *** [master] Error 1

なぜ何かアイデアはありますか?

4

4 に答える 4

51

実装ファイルファイルにインクルードするたびに、構造体の新しいインスタンスが作成されます(そしてオブジェクトファイルに保存されます)。

これを回避するには、ヘッダーファイルで構造体を「extern」として宣言し、実装ファイルで初期化します。

// In your header file: 
extern const struct dsm_config DEFAULT_DSM_CONFIG;

// In your *.c file:
const struct dsm_config DEFAULT_DSM_CONFIG = { AUTO_UNMAP, NO_ENABLE_COA };

これはあなたの問題を解決します。

于 2013-01-25T16:38:19.083 に答える
6

C言語でconstは、オブジェクトにはデフォルトで外部リンケージがあります(C ++ではデフォルトで内部リンケージがあります)。したがって、コードで、DEFAULT_DSM_CONFIG外部リンケージを使用してオブジェクトの複数の定義を作成しました。これは、C言語の定義規則に明らかに違反しています。

オブジェクトをとして宣言するか(内部static constリンケージを持つ複数のオブジェクトを使用してもかまわない場合)、ヘッダーファイルから定義を削除します(定義されていない宣言のみを残します)。extern const

とにかく、質問はこれまで何度も聞かれました。ヘッダーで機能しない定数変数を参照するか、検索を実行してください。

于 2013-01-25T16:49:00.857 に答える
5

ヘッダーファイルを含むすべてのcファイルには次の行があります

const struct dsm_config DEFAULT_DSM_CONFIG = {AUTO_UNMAP、NO_ENABLE_COA};

したがって、これらの各cファイルは変数dsm_configを定義します。変数dsm_configが1つだけ必要な場合は、ヘッダーファイルの宣言を次のように変更する必要があります。

extern const struct dsm_config DEFAULT_DSM_CONFIG;

定義を追加します

const struct dsm_config DEFAULT_DSM_CONFIG = {AUTO_UNMAP、NO_ENABLE_COA};

1つのcファイルのみ。

もう1つの、あまり良くない解決策は、ヘッダーファイルを次のように変更することです。

static const struct dsm_config DEFAULT_DSM_CONFIG = {AUTO_UNMAP、NO_ENABLE_COA};

次に、各cファイルは、リンク時に他の変換ユニットからは見えない独自のdsm_configを定義します。

于 2013-01-25T16:38:18.110 に答える
2

各ソースファイル(.hではなく.c)は個別にコンパイルされます。これらのコンパイルのそれぞれでdsm_config、初期化子(= { values… }部分)を使用したの宣言により、の定義が作成されますdsm_config。したがって、プログラム全体には複数の定義があります。

一般に、ヘッダーファイルはオブジェクトを宣言するだけで、オブジェクトを定義するべきではありません。これを行うには、ヘッダーファイルの初期化子を削除し、初期化子を含まない宣言のみを残します。1つのソースファイルでdsm_config、初期化子を使用して宣言を繰り返して定義します。

于 2013-01-25T16:44:53.500 に答える