忍者ブログ
[PR]
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

【2024年04月29日09:45 】 |
Boehm GC ライブラリインストール
オセロの6x6の解析を行なっている。(4x4の終局画面リスト) 




解析の際、クルクル回していくと起きる現象。



増大するメモリー。



free()しているのに、なぜなんだ?



長年?の疑問が

ttp://www.wakhok.ac.jp/~kanayama/C/01/node134.html

に書かれていた。



ここで注意しなければならないのは、一度free()してしまった 領域を参照したり、利用したりしてはいけないという点です。 C言語でのプログラミングにおけるバグのほとんどは、この malloc() と free()に関連するメモリ管理のバグであると言っても過言では ない位なのです。





はい。そのとおりでございます。



また、free()によって開放したからと言って問題が無い訳では ありません。実は、malloc()をしたメモリの内の幾つかを free() によって開放した場合、メモリは虫食いのように所々が空いた状態になります。 もし、全てのメモリがこのような虫食い状態になってしまうと、大きなメモリ を確保したくても、そのようなブロックが存在しないような場合が生じます。 こうした状態をメモリのスライシングと呼んでいますが、これを 解消するためにはガーベッジコレクションと呼ばれるメモリの掃除が必要と なりますが、残念ながらC言語自体にはそうしたメカニズムは存在していません。 従って、そのような事態が想定される場合にはガーベッジコレクションを サポートした高度なライブラリを別途用意しなければなりません。





ガーベッジコレクション!?

なんだかよくわからないが


どうやら、俺には、ガーベッジコレクションが必要らしい。
(多分)


というわけで、ガーベッジコレクションについてググると、Boehm GC ライブラリがあるらしいことがわかった。


さっそく、MinGWにインストールする。

さて、こまった。普段。MinGWを使用しないのでWindows上のパスがわからねえw.Windows上のファイルパス知るコマンドを知らないので、適当にファイル名を作成し、検索した。



C:\MinGW\msys\1.0\home\root



デフォルトではここらしい。

インストールする。



root@root-PC ~/gc6.8

$ ./configure

checking build system type... i686-pc-mingw32

 :

(略)

 :

$ make

 :

(略)

 :

$ make install



ほーどうやら、珍しくmakeが無事終わったらしい。こういうもんは大概エラーが起きて嫌になるパターンが多い。





幸運に感謝。





http://www.logos.t.u-tokyo.ac.jp/~horita/enshu/info/sample.txt さんのサンプルプログラムを一部修正して実行してみる。(というか、元のサンプルじゃ動かない(笑)。)


ーーーー
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <gc.h>
#include <windows.h> 


#define N 10
#define MALLOC_SIZE 10485760  // 10MB

void make_garbage()
{
   char *dummy = (char *)GC_MALLOC(MALLOC_SIZE);
  //  char *dummy = (char *)malloc(MALLOC_SIZE);
  int i;
  for(i=0; i<MALLOC_SIZE; i+=4096){
    char a = dummy[i];
  }
}

int main()
{
  int i=0;
	
  while(i < N){
    make_garbage();
    printf("made %d bytes of garbage\n", MALLOC_SIZE);
    Sleep(100);
  	i++;
  }
  return 0;
}
 

ーーーーー


root@root-PC ~
$ gcc samp3.cpp -I./gc6.8/include/ -L gc6.8/.libs/ -lgc
 
root@root-PC ~
$ a


にてコンパイル。実行。


はい。





出ましたよ。エラー(笑)。


残念でした。(;_;)



でも、あきらめずに他のバージョンで試してみた。

make 成功 gc6.8         
make 失敗 gc-7.0         
make 失敗 gc-7.1
make 失敗 gc-7.1.tar.gz

とこんな感じでmakeに失敗。

make 成功 gc-7.2alpha6
 


お?キタ━(゚∀゚)━!


gc-7.2alpha6はいけそうだ。当初、gc6.8のmakeに成功したのはたまたま運が良かったらしい。


再度実行。

ーーーーーー
root@root-PC ~
$ gcc samp3.cpp -I./gc-7.2alpha6/include/ -L gc-7.2alpha6/.libs/ -lgc
 
root@root-PC ~
$ a
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
 
root@root-PC ~
$
 

ーーーーーー


キタ━━━(゚∀゚)━( ゚∀)━(  ゚)━(  )━(  )━(゚  )━(∀゚ )━(゚∀゚)━━━!!



比較のため

  char *dummy = (char *)GC_MALLOC(MALLOC_SIZE);
  //  char *dummy = (char *)malloc(MALLOC_SIZE);
  ↓
 // char *dummy = (char *)GC_MALLOC(MALLOC_SIZE);
    char *dummy = (char *)malloc(MALLOC_SIZE);

と修正し、再コンパイル、実行。
ーーーーーー
root@root-PC ~
$ gcc samp3.cpp -I./gc-7.2alpha6/include/ -L gc-7.2alpha6/.libs/ -lgc
 
root@root-PC ~
$ a
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
made 10485760 bytes of garbage
ーーーーー

違いがわからねええwwww


比較のため

#define N 10

#define N 200
 


printf("made %d bytes of garbage\n", MALLOC_SIZE);
を
printf("%03d made %d bytes of garbage\n", i, MALLOC_SIZE);


に変更し



それぞれ実行した結果のタスクマネージャーの状況が以下。




一応。


ガーベレッジ有りの場合が、早く落ちるとはどういうことだ・・?


やっぱりバージョンがアルファだからか・・?


更新が2011年の6月で止まっている。


もっとメモリー使用が、グチャグチャになったら効果を発揮するのだろうか?




よくわからないや。



なお。

-------
#include <gc.h>
#define malloc  GC_malloc
#define calloc  GC_calloc
#define realloc GC_realloc
#define free
-------
と、すれば元のソースを大幅変更せずに使用できるみたいだ。


GC の動作状況を知る



http://www.nminoru.jp/~nminoru/programming/boehm_gc_sample/tree3.c
さんのサンプルによると

ーーーー
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <gc.h>
#include <windows.h> 

typedef struct _Tree_tag {
  struct _Tree_tag* left;
  struct _Tree_tag* right;
} Tree;

Tree* generate_tree(int level) {
  if( level > 0 ){
    Tree* new_tree  = (Tree*)GC_malloc(sizeof(Tree));
    new_tree->left  = generate_tree(level-1);
    new_tree->right = generate_tree(level-1);
    return new_tree;
  } else {
    return (Tree*)0;
  }
}

int main(int argc, char** argv)
{
  int i;

  for(i = 0; i<10 ; i++){
    Tree* root ;
  	
    printf("GC_get_heap_size: %d\n",      GC_get_heap_size() );
    printf("GC_get_free_bytes: %d\n",     GC_get_free_bytes() );
    printf("GC_get_bytes_since_gc: %d\n", GC_get_bytes_since_gc() );
    printf("GC_get_total_bytes: %d\n",    GC_get_total_bytes() );
  	
  	Sleep(1000);
    root = generate_tree(20);
  	
//    printf("GC counts: %d\n", GC_gc_no );
  }

  return 0;
}


ーーーー

にて、分かるらしい。GC_gc_noを使用するには

この方法は、プログラム内部から Boehm GC の状況を 知ることができるのですが、 Java の -verbose:gc 表示のように、 GC が起こる度に状況を報告して欲しい場合があります。Boehm GC では、 ライブラリコンパイル時にこの機能がオフになっています。Makefile の中のコンパイラにあたえるマクロ定義 DEFS の中にある -DSILENT を削除してビルドすることによって、 この機能に対応します。


と、説明されているが面倒なので、この行はコメントアウトした。


それぞれの関数の説明。


size_t GC_get_heap_size(void)      (Boehm GC が管理する)ヒープ領域の大きさサイズ
size_t GC_get_free_bytes(void)      (同)ヒープ領域中の空き領域
size_t GC_get_bytes_since_gc(void)   最後の GC が起きてから割り付けたオブジェクトのサイズ
size_t GC_get_total_bytes(void)      プロセスが起動してから割り付けたオブジェクトの総サイズ
 

コンパイル、実行

root@root-PC ~
$ gcc samp4.cpp -I./gc-7.2alpha6/include/ -L gc-7.2alpha6/.libs/ -lgc
 
root@root-PC ~
$ a
GC_get_heap_size: 0
GC_get_free_bytes: 0
GC_get_bytes_since_gc: 0
GC_get_total_bytes: 0
GC_get_heap_size: 20586496
GC_get_free_bytes: 3710976
GC_get_bytes_since_gc: 1425392
GC_get_total_bytes: 16777200
GC_get_heap_size: 35840000
GC_get_free_bytes: 2117632
GC_get_bytes_since_gc: 6229984
GC_get_total_bytes: 33554400
GC_get_heap_size: 52617216
GC_get_free_bytes: 2105344
GC_get_bytes_since_gc: 23007184
GC_get_total_bytes: 50331600
GC_get_heap_size: 52617216
GC_get_free_bytes: 18878464
GC_get_bytes_since_gc: 14671808
GC_get_total_bytes: 67108800
GC_get_heap_size: 52617216
GC_get_free_bytes: 2101248
GC_get_bytes_since_gc: 31449008
GC_get_total_bytes: 83886000
GC_get_heap_size: 52617216
GC_get_free_bytes: 18874368
GC_get_bytes_since_gc: 14671872
GC_get_total_bytes: 100663200
GC_get_heap_size: 52617216
GC_get_free_bytes: 2097152
GC_get_bytes_since_gc: 31449072
GC_get_total_bytes: 117440400


う~む、つまり。


その、なんだな・・・。



どういうことなんだ?ヽ(^。^;)ノ



まあ、かっこ良く説明したいところだが。
実際、オセロのほうで使用してみて、期待する結果が得られなかったので、ガーベレッジコレクションには興味なくした。



Boehm GC ライブラリにて、free()した部分を再利用出来るかと思ったが、どうも違うらしい。


はてなの説明によると


確保したメモリが使われなくなったことを判断し、自動的に解放する。C言語やC++言語のfree、deleteなどを記述しなくても自動的に解放してくれるので、いつどこでメモリを解放すべきか迷うことなくソフトウェアを開発することができる。


とのこと。


冒頭の一文訂正



どうやら、俺には、ガーベッジコレクションが必要らしい。



必要なかった。






終わり。
PR
【2012年04月19日09:15 】 | 未選択 | コメント(0)
コメントの投稿













前ページ | ホーム | 次ページ

忍者ブログ [PR]