記憶の片隅

Linux/IA32のmallocは一度に2GB弱まで。2GB「弱」というのは、2GBは取れないからだ。2GB制限の理由はずいぶん前にも見たことがあるこのへん(sse.co.jp)を参照のこと。これはファイルサイズの2GB制限と違って時代錯誤的なことではなく、現実に起きて納得の現象だ。そんな制限を承服するかどうかは考え方次第だ。

ではmallocではなくstaticな配列なら2GB以上取れるのか? 同じくらいのサイズまでしか取れないのです。

char mem[1024*1024*1024*2];
int main(int argc, char **argv){}

gcc曰く、「警告: 式の整数がオーバーフローしました」「配列 `mem’ の大きさが負です」…そうかintだから駄目なのか、と思ってunsignedにキャストすると正しい警告が出る。曰く、「配列 `mem’ の大きさが大きすぎます」「`mem’ の領域サイズがわかりません」。

しかしgccが配列のサイズで文句を言うのは気に食わん!

1GBで配列を取ってコンパイルし、アセンブラコードを直して

        .comm   mem,1073741824,32
        .section        .note.GNU-stack,"",@progbits
                           ↓
        .comm   mem,1073741824*2,32
        .section        .note.GNU-stack,"",@progbits

これでコンパイル、リンクは成功する。で、できたバイナリを実行するとsegmentation fault。デバッガからも起動できない…そんなのはあたりまえだ(笑)。

じゃmmap(2)は? /dev/zeroへのmmap(2)を使えばメモリを確保できる。やはりこれも2GB制限があるのだ。MAP_FAILEDが返ってきて、Cannot allocate memoryと言われる。

スタックの場合は実はアセンブラコードを直すと2GBを越えられる。どっかでオーバーフローしてマイナスになっちゃってるのかもしれないし、たぶん動作はしないだろう。ただ、確保する(したつもり)だけでは落ちない。

…我ながら意味のないことばかりやってるな。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です