mallocの動作とコンパイル仕様について

このQ&Aのポイント
  • mallocの動作とコンパイルの仕様について質問があります。
  • 32bitと64bitのUbuntuのgccとMacのgccでの動作の違いについて知りたいです。
  • Ubuntuでのメモリの取得制限と実際の動作が気になります。
回答を見る
  • ベストアンサー

取ってこれないメモリのはずのmallocの動作

こんにちは.mallocの動作,及びコンパイルの仕様について質問です. 以下のような.cのプログラムを書いてgccでコンパイルして実行してみました. #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(int argc, char **argv) { int size = 0; int *tmp = NULL; while(1){ printf("Size %d\n", size++); tmp = (int *)malloc(size * 1024 * 1024); usleep(10000); free(tmp); } } このプログラムだと,heapから取ってこれないぐらい大きいメモリだとなんか起きるのかな?どれぐらいまで取ってこれるのかな?という興味でやってみたのですが, 1)32bit, 64bit ubuntu のgcc (バージョンは覚えてないですけど一番updateされてると思います)では永遠に回り続け, 2)Mac のgccだとSize=2048以降,つまり2GB以降で a.out(1145,0x7fff73a1b310) malloc: ***mach_vm_map(size=18446744071562067968) failed (error code=3) *** error: can't allocate region というエラーをはきます.(プログラムは回り続けます) a. この違いはgccの違いからくるという理解でよろしいですか?Macでの2GBというのもコンパイル側の制約なのでしょうか? b. ubuntuでは実際何が起こってるのでしょう?1000GBとか絶対取れないですけど回ってますし. c. ubuntuで実際に何が起こってるかを確認する方法はありますか.アセンブラとか吐かせるのでしょうか? お時間のあるときに回答してもらえたらと思います.

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

  • ベストアンサー
  • colder
  • ベストアンサー率43% (30/69)
回答No.2

http://linuxjm.sourceforge.jp/html/LDP_man-pages/man3/malloc.3.html >デフォルトでは、Linux は楽観的メモリ配置戦略を用いている。つまり、 malloc() が NULL でない値を返しても、そのメモリが実際に利用可能であること が保証されない。

nasanaut
質問者

お礼

回答ありがとうございます.大変参考になるリッファレンスをありがとうございます.

その他の回答 (3)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

ついでだけど, 「Macでの2GB」ってなんのことですか? 実際に「確保しようとしたサイズ」はいくつですか?

nasanaut
質問者

お礼

返信ありがとうございます.上のプログラムは確保するsizeをインクリメントしていき,どこでどういう動作になるか見るプログラムでした.2GBというのは,Macがエラーを吐き始めたsize=2048, つまり2048*1024*1024byteで2GBという意味でした.

回答No.3

tmp が NULL でないことを検証せにゃイカンのとちゃいます? mallocはメモリが確保できんかったらNULL返すんしょ?

nasanaut
質問者

お礼

回答ありがとうございます.チェックしてみたところ僕の環境だとMac, Ubuntuともに2048MB=2GB確保しようとしたところでNULLが返ってくるようですね.

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

エラーが出るかどうかは OS の違いだと思う. で, malloc でメモリが取れなかったときどうなるか, 仕様をちゃんと確認してください.

nasanaut
質問者

お礼

返信ありがとうございます.OSの違いのようですね.もう少し勉強してみます.

関連するQ&A

  • mallocについて

    vine linux 3.0上でgccを使い下記のようなプログラム(読みにくいプログラムで申し訳ありません)を作成してみました。無事コンパイルも通りメモリも確保出来ました。 しかし、このプログラムを2つ起動しそれぞれでメモリを確保するとおかしな事が起きるのです。どういう症状かと言うとプログラム1もプログラム2も同じ先頭アドレスを確保しているのです。 例) プログラム1 keep memory size : 11 address : 0x8049700 プログラム2 keep memory size : 11 address : 0x8049700 なぜこのような事が起こるのでしょうか? ご教授宜しくお願いします。 #include <stdio.h> #include <stdlib.h> main(int argc, char *argv[]) { int size; unsigned int *p; char buf; size = atoi(argv[1]); printf("keep memory size : %d\n", size); p = (unsigned int *)malloc(size); printf("address : %p\n", p); scanf("%c", &buf); free(p); }

  • malloc領域から関数ポインタ型で呼び出し

    現在C言語で,関数ポインタ型による関数の呼び出しを勉強しています. print()という関数は受け取った文字列を表示するだけの関数ですが, これを通常の関数ポインタを用いて実行したのがmain内の(*mem)("FROM POINTER.");です. これに対して後半は,mallocで確保した領域にmemcpyでprint()をコピーし, (*mem)("FROM COPIED AREA.");で実行しています. 実行環境は以下の通りです. OS:Windows7 Personal 32bit CPU:Intel Core i5 M430 統合開発環境:Visual C++ 2010 Express Edition コンパイルには成功しています. 実行すると"FROM POINTER."は表示されるのですが, "FROM COPIED AREA."は表示されず,プログラムが動作を停止してしまいます. mem = (void (*)(char*))tmp;までは実行できているようですが, (*mem)("FROM COPIED AREA.");の実行の時点で停止しているようです. またコマンドプロンプトからBorland C++ 5.5.1でコンパイルしても, 同じように動作が停止してしまいます. ただし同じプログラムでも,Cygwinからgccでコンパイルすると, 意図した通りの挙動となっていることを確認しています. コンパイラの違いによるものなのか, UNIXとWindowsの違いによるものなのか判断できずにいます. (もしくはライブラリのmalloc,memcpy辺りの実装法の違いでしょうか?) どなたかご存知でしょうか. ----------------------------------------- #include<stdio.h> #include<stdlib.h> #include<string.h> #define SIZE 512 void print(char* str){ printf("%s\n", str); } int main(int argc, char** argv){ void (*mem)(char*); void *tmp; mem = &print; (*mem)("FROM POINTER."); tmp = malloc(SIZE); memcpy(tmp, print, SIZE); mem = (void (*)(char*))tmp; (*mem)("FROM COPIED AREA."); }

  • malloc関数の使い方について(初心者)

    膨大なデータ数を扱うためにmalloc関数を用いて配列にデータを格納し、それを表示するプログラムを考えました。コンパイルはできるのですが、実行するとエラーが起こります。freeの開放の仕方が間違っているのでしょうか?よろしくお願いします。 /*ソース*/ #include <stdio.h> #include <stdlib.h> #define N 130000 int main(void) { double *p; int i; p = malloc(N); if(!p){ printf("割り当てエラー"); exit(1); } for(i=0;i<N;i++){ p[i]=i; printf("%f\n",p[i]); } free(p); }

  • 64bit系でのmalloc

    こんにちは itanium2の乗っているマシンでcのプログラムをつくっています。 gccでコンパイルしているのですが、 warningが出てコンパイルができません。 以下のようなエラーです。 warning: cast to pointer from integer of different size 引っかかっている場所は、 double *ini=(double *)malloc(sizeof(double)*1000000); という場所です。配列iniのサイズが小さいうちは以下のように double ini[10000] とすれば、通るのですが、大きなメモリ領域を確保しようと mallocを使うと上のようなエラーが出て、コンパイルできません。 調べてみると、64ビット系で起こるエラーであるということは わかったのですが、回避の仕方がわかりません。 どなたかご存じの方がいらっしゃったらお教えください。 OSはレッドハット8でカーネルは2.4.24です。

  • malloc メモリリークについて

    #include<stdio.h> #include<stdlib.h> void alloconly(void) { const int sz=10; static int n=0; void *p; p=(void*)malloc(sz); if(p==NULL){ printf("動的確保不可 %d\n",n+1); printf("確保メモリサイズ %d byte\n",sz*n); exit(-1); } ++n; } int main(void) { for(;;){ alloconly(); } }と言うプログラムがある本に載っており、回答として   動的確保不可 *******(数字)   確保メモリサイズ *********byte(数字)となっていますが私の環境(Reshat Linux)では   強制終了します で終了してしまいます。原因が判らず困っています。ご解答願います。

  • mallocについて

    mallocについて 現在C言語でプログラムをかいているのですが、原因不明のエラーが出て困っています。 それはmallocによる動的メモリ確保を行ったとき、 (float *)malloc(sizeof(float)*200)の場合大丈夫ですが、 (float *)malloc(sizeof(float)*320)ではエラーが出てしまうのです。 しかし (float **)malloc(sizeof(float*)*640)とした場合エラーは出ませんでした。 これは何が原因でエラーが出ているのでしょうか? ちなみにコンパイルはできており、実行したとき プログラム名(7637) malloc: *** error for object 0x100ff7a08: incorrect checksum for freed object - object was probably modified after being freed. *** set a breakpoint in malloc_error_break to debug というエラーがでます。

  • mallocで引数に変数を入れると警告がでます

    #include<stdio.h> int main(void){ int n,i; int* array; puts("n=?"); scanf("%d",&n); array = (int*)malloc(sizeof(int) * n); for(i=0;i<n;i++) *(array+i) = i; for(i=0;i<n;i++) printf("%d ",*(array+i)); puts(""); return 0; } C言語で、上述のプログラムをコンパイルしたところ、 9: warning: incompatible implicit declaration of built-in function ‘malloc’ と警告がでます。 ./a.outで普通に実行できるのですが、 警告がでるということは、もっと正しいやり方があるということでしょうか?

  • mallocがうまく動かない

    コマンドライン引数で指定された文字列を逆順に返すプログラムを作るため 下記のようなプログラムを組みました。 ところが変数strの大きさがargv[1]より大きくなってしまいます。 どうすればよいのでしょうか。 #include <stdio.h> #include <stdlib.h> char *mstrrev (char *s); int main(int argc, char *argv[]){ char *str; str = mstrrev(*(argv+1)); printf("%s",str); free(str); } char *mstrrev (char *s){ int length,i; char *str; for(length=0;*(s+length)!='\0';length++); str = (char *)malloc(sizeof(char)*length); for(i=0;i<length;i++){ str[i] = s[length-1-i]; } return str; }

  • C言語 動的なメモリの確保 実行できない

    malloc関数を使いメモリを確保しそこへ"ABCD"と記憶させ、ポインタ*Cを使い確保したメモリの内容を表示するプログラムです。 ********************************************* #include <stdio.h> #include <stdlib.h> int main(void) {   int i;   char *C;   C = (char *) malloc (sizeof(char) * 5);   C = "ABCD";   for(i = 0; i < 5; i++){     if(C[i] != NULL){       printf("%s", C[i]);    ←※エラー※     }   }   free(C);   return 0; } ********************************************* 正常にコンパイルできますが実行エラーになります。VCを使いF10のデバッグテストで※のところエラーになります。なぜなのでしょうか?

  • C言語のポインタ

    あまり意識せずにポインタを使っているせいか,次のプログラムではまってしまいました. #include<stdio.h> #include<stdlib.h> int main(void) {  int *p, q;  p = (int *)malloc(sizeof(int));  q = (int *)malloc(sizeof(int));  *p = 2;  printf("%d\n", *p);  return 0; } コンパイルエラーで実行ファイルが出力されません. このプログラムで変数qはなぜポインタじゃないのでしょうか? 次にtypedefでptr_intという型を定義したプログラムは, 上のようなエラーが出力されず,期待とおりの結果になりました. #include<stdio.h> #include<stdlib.h> typedef int* ptr_int; int main(void) {  ptr_int p, q;  p = (int *)malloc(sizeof(int));  q = (int *)malloc(sizeof(int));  *p = 2;  *q = 3;  printf("%d\n", *p);  printf("%d\n", *q); return 0; } typedefすることでなぜエラーを回避することができるのでしょうか? よろしくおねがいします.

専門家に質問してみよう