• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:mallocの挙動について)

mallocの挙動について

このQ&Aのポイント
  • C言語で書かれた32bitアプリを32bitのサーバAと64bitのサーバBで実行したところ、サーバBではmallocでNULLポインタが返され異常終了した。
  • サーバAは正常終了し、期待した実行結果が得られています。
  • プロジェクトの設定で2GBを越えるアドレスをサポートするオプションを設定すれば、サーバBでもアプリが正常終了するようになりました。しかし、このオプションがない場合にメモリが多いサーバでmallocのメモリ確保が失敗する関連性については理解できていません。

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

  • ベストアンサー
回答No.1

・2Gを超えるメモリをサポートしない場合の挙動 「メモリアドレスは2Gを超えない」と言う前提で処理されます(メモリアドレスを32ビットで扱います) 従って、OSに対してメモリ確保を要求した時、戻り値を「32ビット整数で、正数なら成功、負数なら失敗」と扱います。 なので、OSが「2G以降のアドレスを返す」と「32ビット整数で負数」となるため、メモリ確保に成功しているにも関わらず、失敗したと誤解して処理を継続します(最終的にはmallocがNULLを返します) サーバーAでは、3GBオプションがオフなので「ユーザーメモリは前半2G、カーネルメモリは後半2G」となります。 ユーザーメモリが前半2Gの範囲に限定されるので、OSは、メモリ確保成功時「2G以降のアドレスは返さない」ので「32ビット整数で、正数なら成功、負数なら失敗」と扱っても問題は起きません。 しかし、サーバーBでは(デフォルト設定ならば)「ユーザーメモリは前半4G、カーネルメモリは後半2G」となります。 ユーザーメモリが前半2Gの範囲に固定されないので、OSは、メモリ確保成功時「32ビット整数で、正数や負数になるアドレスを返す」ので「正数なら成功、負数なら失敗」と扱うと問題が起きます。 ・2Gを超えるメモリをサポートする場合の挙動 「メモリアドレスは2Gを超える」と言う前提で処理されます(メモリアドレスを64ビットで扱います) 従って、OSに対してメモリ確保を要求した時、戻り値は「64ビット整数で、正数なら成功、負数なら失敗」と扱います。 成功時には「32ビット整数で負数になる、2G以降のアドレスも、正しくアドレスとして扱う」ので、成功しているのに失敗と勘違いする事はありません。 例え「メモリ使用量が2G未満」だとしても「物理アドレスが2G(0x7FFFFFFF)を超える可能性があるシステム」では「2Gを超えるメモリをサポートする」にしなければなりません。 今回の場合、サーバーAは「ユーザーメモリの物理アドレスが0x00000000~0x7FFFFFFFの範囲に限定される」ので「2Gを超えるメモリをサポートしない」でも「偶然、うまくいっただけ」です。 もし、サーバーAに「3Gオプション」を付けていたら「ユーザーメモリの物理アドレスが2G(0x7FFFFFFFF)を超え、サーバーBと同様の結果になっていた筈です。 重要なのは「使用量が2Gを超えるか?」ではなく「メモリアドレス(物理アドレス)が2Gを超えるか?」なのです。

Nu-GGG
質問者

お礼

なるほど! 目から鱗です! 最近、メモリ使用量がネックになるシステムをいっぱい改修してたので、どうもメモリ使用量に固執してたみたいです。 冷静に考えるとアプリが32bitである以上、OSから2GB以降のアドレス返されたらどうしようもないですよね^^; 大変納得できました。丁寧に解説頂き有難うございました。

すると、全ての回答が全文表示されます。

関連するQ&A