1

if次のスニペットの条件を実行するために次のコードを作成できる可能性のあるケースは何ですか? 私に関する限り、ifステートメントが実行される原因を関連付けることはできません。

#include <stdio.h>
#include <stdlib.h>
void main(void){
int Nod = 1024 * 8; //Nod contains the number of nodes
double *MM; //MM is a square matrix it can contain very large number of data 10^10
MM = calloc(8 * Nod * 8 * Nod, sizeof(double));
if (MM == NULL)exit(0);
//then MM will then be passed to some other functions say
eigenvalue(MM);}

非常に大きなプログラムの途中でこのチェックを行う FEM コードを使用しています。興味深いことに、コードを実行すると、異常な動作が示されます。ここでプログラムが停止することがあります。時々それはうまくいきます。言及する価値のあることの 1 つは、プログラムが粗いメッシュで実行される場合です。つまり、Nod計算するノードの数が少ない場合、プログラムは問題なく動作します。しかし、細かいメッシュを使用すると、残念ながらプログラムがクラッシュします。このプログラムは、128GB の RAM を搭載したミニ ワークステーションで実行されます。プログラムは 1GB (またはその程度) の RAM を占有します。

4

2 に答える 2

6

2 つの明らかな問題:

  1. 計算8 * Nod * 8 * Nodはタイプintになりますが、(プラットフォーム上で) 結果を保持するのに十分な大きさではない可能性があります。size_t Nodおそらく代わりに欲しいでしょう。__builtin_mul_overflow()また、値が一定でない場合は、(おそらく GCC のようなプラットフォーム固有の関数を使用して) オーバーフローをチェックすることもできます。
  2. calloc()ではないことを確認せずに の結果を使用しますNULL。アロケーターが十分な大きさの連続したブロックを見つけられない場合、アロケーターは失敗します。続行する前にそれをテストする必要があります。

エラーを報告するために使用するライブラリ関数からの戻り値を決して無視しないでください。

于 2017-03-13T09:55:43.803 に答える
0

From the man page:

   The malloc() and calloc() functions return a pointer to the allocated  memory  that
   is  suitably  aligned  for  any kind of variable.  On error, these functions return
   NULL.  NULL may also be returned by a successful call to malloc() with  a  size  of
   zero, or by a successful call to calloc() with nmemb or size equal to zero.e here

Now in your case it's not dew to allocating zero sized memory so the only other reason for returning NULL is failure to allocate the memory. In the snippet you show you are allocating 4294967296 elements (1024 * 1024 * 64 * 64) the size of a double (8 bytes) that's 32Gb of ram. Now your system definitely has that amount of ram but at any given time it may not have it all in a consecutive allocable block so calloc may be failing for that reason.

Another thing to watch out for is memory overcommitment governed primarily by

/proc/sys/vm/overcommit_memory
or vis sysctl  vm.overcommit_memory

by default overcommit_memory is set to 0 but possibly the safest combination would be setting it to 2. See proc man page or kernel Documentation/vm/overcommit-accounting for more detail on this.

vm.overcommit_ratio
vm.overcommit_kbytes
vm.nr_overcommit_hugepages

are also other sysctl settings that govern if/how your system will deal with memory overcommitment.

Even at this I've done my best not to allow overcommitment of memory on a 32 bit linux machine but I was still able to get the huge 32Gb callot not to return null (which I regard as being strange on it's own as a PAE less 32 bit machine can only address a total of 4Gb of virtual memory, and even if it had PAE it would only allow addressing 4Gb at a time).

于 2017-03-13T10:11:12.407 に答える