6

これが私のコードです:

#define MSK 0x0F
#define UNT 1
#define N 3000000000

unsigned char aln[1+N];
unsigned char pileup[1+N];

void set(unsigned long i)
{
    if ((aln[i] & MSK) != MSK ) {
        aln[i] += UNT;
    }
}
int main(void) {}

コンパイルしようとすると、コンパイラは次のように文句を言います。

 tmp/ccJ4IgSa.o: In function `set':
 bitmacs.c:(.text+0xf): relocation truncated to fit: R_X86_64_32S against symbol `aln' defined in COMMON \
 section in /tmp/ccJ4IgSa.o
  bitmacs.c:(.text+0x29): relocation truncated to fit: R_X86_64_32S against symbol `aln' defined in COMMON\
 section in /tmp/ccJ4IgSa.o
 bitmacs.c:(.text+0x32): relocation truncated to fit: R_X86_64_32S against symbol `aln' defined in COMMON\
  section in /tmp/ccJ4IgSa.o

NNを2000000000に変更すると正常にコンパイルできるので、理由が大きすぎるのではないかと思います。しかし、Nの値として3000000000が必要です。

誰かがそれについて考えていますか?

4

5 に答える 5

7

元の質問によると、整数リテラルの接尾辞UL(または同様のもの)を使用して、Nのストレージタイプを強制します。

#define N 3000000000UL

ただし、(HLundvallの回答に対するコメントによると)relocation truncated to fitエラーは明らかにこれが原因ではありません。(MysticalとMatt Laceyが言うように)単に大きすぎてセグメントに収まらない可能性があります。


余談ですが、巨大なアレイで何を達成しようとしているのかを説明する別の質問をすると、誰かがより良い解決策を提案できる可能性があります(メモリに収まる可能性が高くなります)

例えば:

  • サンプルコードは、示されているコードの各バイトの下位ニブルのみを使用しています。これを半分のサイズにパックすることができます(これは確かにまだ大きすぎます)
  • アクセスパターンによっては、アレイをディスク上に保持し、動作中のサブセットをメモリにキャッシュできる場合があります
  • 必要なものがわかっていれば、全体的なアルゴリズムとデータ構造が改善される可能性があります
于 2012-08-15T23:43:09.970 に答える
5

数値リテラルが正しいタイプではないという「正式な」問題を無視すると(正しい構文については他の回答を参照)、ここでの重要なポイントは、3GBの静的/グローバル配列を割り当てることは非常に悪い考えであるということです。

staticまた、ほとんどのプラットフォームのグローバル1変数は、実行可能ファイルのイメージから直接マッピングされます。つまり、実行可能ファイルは3 GBまでの大きさである必要があります。これは、現在の標準でもかなり大きいものです。一部のプラットフォームでこの制限が解除される場合でも(コメントを参照)、割り当ての失敗を処理する方法を制御することはできません。

最も重要なことは、グローバル変数はそのような大きなものを対象としておらず、リンカー(見つけたものなど)とローダーによって課せられた任意の制限に関する問題を見つける可能性があります。malloc代わりに、newまたはプラットフォーム固有の関数を使用して、ヒープ上に数KBを超えるものを割り当て、実行時に発生する可能性のある障害を適切に処理する必要があります。

それでも、ほぼすべての32ビットオペレーティングシステムで実行されているアプリケーションの場合、要求に応じて3 GBの連続したメモリを取得することはできず、これらのアレイを複数(= 4GBを超える)取得することはまったく不可能であることに注意してください。プラットフォーム固有のトリックに頼ることなく(たとえば、特定の瞬間にメモリ内のアレイの特定の部分のみをマッピングする)、連続したメモリ)。

また、プログラムが実行を開始してから、すべての連続したメモリが必要であると確信していますか?すべてのメモリの割り当てを回避できる、より優れたデータ構造/アルゴリズムはありませんか?


  1. 一般に、標準で静的ストレージ期間を持つ変数と呼ばれるもの。
于 2012-08-15T23:48:46.417 に答える
1

unsigned long型の数値定数を入力するには、次のようにします。

#define N 3000000000UL
于 2012-08-15T23:43:39.890 に答える
1

問題は、gcc(デフォルト)がpc相対アクセスを使用してx86_64ターゲット上の静的データオブジェクトのアドレスを取得し、それらのアクセスが最大2^31バイトに制限されていることです。したがって、シンボルにアクセスするコードから2 GB以上離れた場所にシンボルが配置された場合、シンボルで許可されている32ビットのスペースに収まらないほど大きいオフセットを使用しようとすると、このリンクエラーが発生します。命令。

-mcmodel=largegccのオプションを使用すると、この問題を回避できます。これは、32ビットPC相対オフセットを使用してシンボルにアクセスできると想定しないように指示します(特に)

定数リテラルの型接尾辞はほとんど関係がないことに注意してください。intに対して大きすぎる定数リテラルは、接尾辞なしで自動的にlong(または必要に応じてlong long)になります。C99仕様の6.4.4.1.5を参照してください。

于 2012-08-16T00:18:13.793 に答える
-1

実行可能ファイルは、許可されていない4GBマークを超えてオブジェクトをメモリに入れようとしています。このリンクを参照してください:http ://www.technovelty.org/code/c/relocation-truncated.html 。

記事から:「これが表示されていて、手動でコーディングしていない場合は、gccの-mmodel引数を確認することをお勧めします。」

于 2012-08-16T00:24:43.677 に答える