16

次のコードは例外をスローせず、「成功」を出力します。なんで ?

#include <iostream>

int main() 
{
    size_t size = size_t(1024)*1024*1024*1024*1024*1024*1024*1024;
    char* data = new char[size];

    if (data == NULL)
        std::cout << "fail" << std::endl;
    else
        std::cout << "success" << std::endl;

    return 0;
}
  • コンパイラ: g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
  • OS: Ubuntu 12.04
  • RAM: 8GB

そして、これが本来の動作方法である場合、十分なメモリがあることを確認するにはどうすればよいですか?

[編集:愚かなコードをもう少し正確にしました。2 つ削除すると、少なくとも x64 で失敗するようになりました*1024]

4

5 に答える 5

20

私のコンパイラはこれに答えることができます:

$ g++ --version
g++ (GCC) 4.7.1 20120721 (prerelease)
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ g++ -Wall -Wextra -pedantic q12507456.c++
q12507456.c++: In function 'int main()':
q12507456.c++:5:42: warning: integer overflow in expression [-Woverflow]
$
于 2012-09-20T07:16:49.837 に答える
6

これは、要求している数値が大きすぎて整数内に格納できず、ここでオーバーフローが発生し、割り当てられたメモリが実際には思ったよりはるかに少ないという事実である可能性が高いです。

ここでは、 http://en.wikipedia.org/wiki/Yobibyteによると2 ^ 80=1208925819614629174706176です。

于 2012-09-20T07:01:29.707 に答える
5
1024*1024*1024*1024*1024*1024*1024*1024

計算時に整数のオーバーフローが発生します。つまり、2 ^ 32(または、システムによっては2 ^ 64)を法として取得され、割り当て可能なゼロバイトになります。

于 2012-09-20T07:02:21.177 に答える
4

Linux malloc(最終的には をサポート) ではオーバーコミットnewできることに注意してください。

2.1.27 以降、sysctlVM_OVERCOMMIT_MEMORYおよび proc ファイル /proc/sys/vm/overcommit_memory があり、値は 1: オーバーコミットを行い、0 (デフォルト): 行いません。

malloc成功して VA を予約しますが、ページでバックアップしません。ページにアクセスすると、コミットに成功する場合と失敗する場合があります。OOM Killerが実行される場合があります。すべてが失敗した場合は、アクセス時に GPF を取得します。

この行動が狂っているのか(正気な人がこのキャンプにいる)か、素晴らしい(狂った人がそのキャンプにいる)かについては、意見が分かれています。

于 2012-09-20T07:23:39.173 に答える
1

ご存知かもしれませんが、念のため記載しておきます。例外は文字通りスローされていません。コードは if ステートメントによってテストされています。テストに使用する用語や方法に関係なく、注意すべきより関連性の高い観察結果があります。システムは整数の最大値を保持しており、C++ はチェックを行い、それに応じて何らかの方法で動作することにより、コンパイル中にそれを考慮します。繰り返しますが、あなたもすでに知っているかもしれません。私の推測では、値が 0 に戻ってから過剰な量になるか、ポインターが指し始める前に存在していた値がそのまま保持されていた可能性があります (ほとんどの場合)。その場合、ポインターはNULL. 作ってみてくださいNULL宣言時に、メモリを割り当てて天気を確認し、if ステートメントに合格するかどうかを確認します。

于 2012-09-20T07:20:50.917 に答える