• ベストアンサー

同じ配列またはクラスを、2回以上newしたとき

ファイルサイズ不定(ただし最大は10KB)のファイルを複数個読み込む際、ファイル個数分の配列を用意し生成するとメモリ不足になりかねないので、 読み込んだデータを使い終わったらすぐに破棄して別のデータを生成するといったような、1つの配列を使い回す方法を考えています。 (読み込んだbyte型の配列データは即座に4byte区切りでint型配列に変換し格納しています) C++なら  int *p;  p = new int[1024*10];  delete p;  p = new int[1024*10];  delete p; みたいな方法で明示的に解放ができますが、 Javaではガーベッジコレクションで自動回収されるので 任意のタイミングで解放できないので、 int p[] = new int[1024*10]; p = null; p = new int[1024*10]; p = null; みたいな方法で試しているのですが、 こういった方法はやっぱりマズいのでしょうか? JAVAヒープの容量を見る限りでは特に変化は見られず、素人の私では判断できないので、もしもご存知の方がいらっしゃればアドバイスいただけると助かります。 よろしくお願いします

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

  • ベストアンサー
  • osumitan
  • ベストアンサー率33% (102/307)
回答No.3

基本的にはその考え方でいいと思います。 ちなみにあえていちいちnullを代入しなくても、次のnewした配列を代入すれば 前の配列は参照されなくなるので、ガーベジコレクションの対象になります。 ただ、不要になったらガーベジコレクションで自動的に解放してくれると言っても、 短時間で急速に大量のインスタンスを生成すると、解放処理が追いつかなかったり、 追いついても解放処理のせいでパフォーマンスが低下する可能性があります。 質問の例のように配列を生成しては破棄するの繰り返しをやると、そうなる可能性があります。 配列の個数が1024*10と決まっているのであれば、newするのは最初だけにして、 2回目移行は内容の書き換えで対応した方が、ヒープの使用効率という点では現実的でしょう。 配列の個数が決まっていなくても、最大の個数がわかるのなら、やはりそのようにすべきでしょう。 あと思ったのは、どうしても同時に10*1024のintが必要なのかな?ということでした。 intひとつずつ処理するようなやり方できないのかなーと。 Javaはガーベジコレクションがあるからメモリ確保し放題というわけではもちろんなく、 生成しなくて済むインスタンスはできるだけ生成しない方が望ましいですし、 メモリリークのような現象もあります。 (すでに不要なインスタンスを気づかずライフサイクルが長い場所で参照しちゃってて解放されない、みたいな)

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

その他の回答 (2)

  • nknk80
  • ベストアンサー率65% (17/26)
回答No.2

> Javaではガーベッジコレクションで自動回収されるので > 任意のタイミングで解放できないので、 > > int p[] = new int[1024*10]; > p = null; > p = new int[1024*10]; > p = null; > > みたいな方法で試しているのですが、 Javaではガーベッジコレクションが機能するので、 この使い方で問題ありません。 任意のタイミングで解放しなくても、 実行中にメモリ解放の必要性がでてきたら 自動的に解放してくれます。

全文を見る
すると、全ての回答が全文表示されます。
回答No.1

メモリ領域が厳しいと言う前提条件でなら、単純に内容をクリアしては如何でしょう?(あるいは、クリアせずに領域を再利用できるように、データサイズを別に保持するとか。)

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

関連するQ&A

  • newで個別に生成した配列にNULLを代入しても大丈夫か

    C++にて要素数が不定の配列のクラスをnewで生成します。 このとき、newで一度に全ての配列を生成するとメモリをかなり取るので、 指定された要素番号のみを生成したいのでダブルポインタにし、 全体を生成してから個別にクラスを生成することで、 思い通りの処理ができるようになりました。 (生成する番号は0→1→2みたいな順列ではないため) しかし、ここで1つ問題が発生しました。 まずは以下にそのソースを示します。 ----------------------------- class CHOGE {   int a; public:   CHOGE(){ a=999; }   void print(){ cout<<a<<endl; } }; ----------------------------- void main(){   CHOGE **p = new CHOGE*[3];   if( p[0] != NULL ){ // ←条件を通過してしまう     cout << "ほげ~" << endl; // ←表示される     //p[0]->print(); // ←当然エラー   }   p[0] = new CHOGE();   p[0]->print(); // ←OK   delete p[0];   p[0] = NULL;   delete [] p;   p = NULL; } ----------------------------- 上記は3個の要素の配列を生成してから、 個別に0番目の要素のインスタンスを生成しています。 しかし、上記main関数の3行目では、 インスタンスはまだ生成していなにもかかわらず NULLチェックを通り過ぎてしまいます。 そこで上記main関数の2行目に  for(int i=0; i<3; i++) p[i] = NULL; という処理を入れると期待通りに動いてくれるのですが、 どうも引っかかるといいますか、何かの情報を消してしまったり やってはいけないことをやってそうで、不安なのです・・・。 上記のようなとき、NULLを代入しても大丈夫なのでしょうか?

  • JAVAのNEW配列生成とガベージコレクション解放

    ある本に、IF文内での、JAVAの配列生成で、IF文のブロックを内で生成した配列が、ブロックを抜けた際の挙動が異なると書いてありました。 NEWを使わないで生成した配列では、解放されるが(例 int[] k = {10 , 20 , 30}; ) NEWを使って生成した配列(例 int[] hoge = new int {3}; )は メモリー内に残ってしまうということでしたが、多分その後 ガベージコレクションで解放されると思いますので問題はないのですが 両者とも、メモリー内に作成(用意)された同じような変数の箱を利用しているのに どうして挙動が異なるのでしょうか? NEWを使わないで生成した配列kは、例えばk[0]の中にアドレス参照でなく 10という値がそのまま入るのでしょうか? 分かりやすく教えていただけると助かります。 よろしくお願いいたします。

    • ベストアンサー
    • Java
  • 多次元配列のメモリ解放

    多次元配列のメモリ解放についてです。 以下のような方法で多次元配列を確保した場合に、 --- char** ppMain; ppMain = new char*[3]; for (int i = 0; i < 3; i++){ ppMain[i] = new char[20]; } --- メモリ解放する場合、 --- for (int i = 0; i < 3; i++){ delete [] ppMain[i]; ppMain[i] = NULL; } delete [] ppMain; ppMain = NULL; --- で良いでしょうか? おそらく、new/deleteの回数が同じであれば問題ないと思うのですが。 少し混乱してしまって、 delete [] ppMain[i]; によって new char*[3]で確保したところも解放されており delete [] ppMain; が必要なく危険な領域まで解放しようとしているということはないでしょうか? ご専門、お詳しいかたコメント宜しくお願いします。

  • 多次元配列の new

    多次元配列を new すると、どのような型のサイズの領域の配列が確保されるんでしょうか?たとえば、  int (*a)[2] = new int[3][2]; とすると、  1. 長さ2のintの配列へのポインタ型の長さ3の配列の領域が確保される のか、  2. int[3][2] すなわち、int が 6 つ分の領域が確保される のか。 今まで、「そりゃあ 2 の方だろう」と信じ込んであまり考えずにいたんですが、「コードの型形式からすると 1 の方の解釈でもいいよなぁ」と、ふと思ったものですから、質問させていただきました。 わたしの環境で調べてみると(配列用のハウスキーピング的な余分の領域とか、パディングなどは無視して)、確かに 1 の方なんですか、これで標準準拠なんでしょうかね?^^; XP Home Edition Ver.2002 SP2 cygwin v.1.0.2-1 GNU g++ v.4.1.1 ===== #include <iostream> #include <new> #include <cstdlib> struct A { char a; void *operator new(std::size_t s) { void *p = std::malloc(s); std::cout << "A::new(): " << p << '\t' << s << '\n'; return p; } void operator delete(void *p, std::size_t s) { std::cout << "A::delete(): " << p << '\t' << s << '\n'; if (p) std::free(p); } void *operator new[](std::size_t s) { void *p = std::malloc(s); std::cout << "A::new[](): " << p << '\t' << s << '\n'; return p; } void operator delete[](void *p, std::size_t s) { std::cout << "A::delete[](): " << p << '\t' << s << '\n'; if (p) std::free(p); } }; int main() { std::cout << sizeof(char) << '\t' << sizeof(A) << '\t' << sizeof(A(*)[8]) << '\n'; A *a = new A; std::cout << a << '\n'; A *aa = new A[8]; std::cout << aa << '\n'; A (*aaa)[8] = new A[8][8]; std::cout << aaa << '\n'; A (*aaaa)[8][8] = new A[8][8][8]; std::cout << aaaa << '\n'; delete[] aaaa; delete[] aaa; delete[] aa; delete a; } ===== % ./a.exe 1 1 4 A::new(): 0x870668 1 0x870668 A::new[](): 0x870678 12 0x87067c A::new[](): 0x870688 68 0x87068c A::new[](): 0x8706d0 516 0x8706d4 A::delete[](): 0x8706d0 516 A::delete[](): 0x870688 68 A::delete[](): 0x870678 12 A::delete(): 0x870668 1

  • 3次元配列の動的確保

    2次元配列は、 // 動的確保 int **mat = new int*[row]; for(i = 0; i < row; i++) mat[i] = new int[col]; //解放 for(i = 0; i < row; i++) delete [] mat[i]; delete [] mat; で、生成と開放はできたのですが、3次元となると、途端にわからなくなります。 かれこれ1時間半は試行錯誤はしているのですが、たどり着きそうにありません。 どなたかご教授願います。

  • 多次元配列の new 2

    追加の質問ですみません^^; char の8個の配列へのポインタの配列を new する場合などは、以下のサンプルのように typedef しないとかけないんでしょうかね?たとえば、  char (**bb)[8] = new (char (*)[8])[8]; 書きたいように思いますが、これは文法違反ですし・・・^^; ==== サンプル:(iostream の初期化時に、定義した new が呼び出されるかもしれないことを一応考慮して、stdio の関数を使っています^^) #include <new> #include <stdlib.h> #include <stdio.h> void *operator new(std::size_t s) { void *p = malloc(s); fprintf(stderr, "::new(): %p\t%lu\n", p, (unsigned long)s); return p; } void operator delete(void *p) { fprintf(stderr, "::delete(): %p\n", p); if (p) free(p); } void *operator new[](std::size_t s) { void *p = malloc(s); fprintf(stderr, "::new[](): %p\t%lu\n", p, (unsigned long)s); return p; } void operator delete[](void *p) { fprintf(stderr, "::delete[](): %p\n", p); if (p) free(p); } int main() { typedef char (*T)[8]; char (**b)[8] = new T[8]; delete[] b; } ==== % ./a.exe ::new[](): 0x6e01b0 32 ::delete[](): 0x6e01b0

  • newとdelete

    動的にaaa[5][40]という配列を作りたいのですけど,以下のプログラムでよろしいでしょうか? aaa = new double *[5]; for(int p = 0; p < 5; p++){ aaa[p] = new double [40]; } また,これをdeleteするときはどのようにすればよろしいのでしょうか? どうぞよろしくお願いいたします.

  • STLを使わずに可変長配列を再現する方法

    STLのlistが(配列に比べると)想像以上に遅かったので C++で可変長配列を再現したいのですけども 配列の拡張が思った以上に遅く困っています。 毎回newではオーバーヘッドが発生しますので、 現在は配列を一定数確保しておき 足りなくなったら配列を拡張(再確保)しています。 現在の配列のアドレスを一旦退避させてdeleteし、 新たにnewで生成して復帰させるといった感じです。 ただしこれでは、配列の要素数が増えるほど遅くなり、 オブジェクトの参照ならまだしも実体の場合は 全てコピーしなければならないので、 場合によってはSTLのlistよりも遅くなってしまいます。 newで生成してるのでできればreallocは使わずに 再現したいのですが、どうにか方法は無いでしょうか? よろしくおねがいします。 //----------------------------------------------- struct Test {   int val;   Test( int _val ){ val=_val; } }; Test obj1( 1 ); Test obj2( 2 ); Test obj3( 3 ); // 元のデータに代入 Test **ptr = new Test*[2]; ptr[0] = &obj1; ptr[1] = &obj2; // 退避させる Test **tmp = new Test*[2]; for( int i=0; i<2; i++ ) tmp[i] = ptr[i]; // 拡張する delete [] ptr; ptr = new Test*[4]; // 復帰させる for( int i=0; i<2; i++ ) ptr[i] = tmp[i]; delete [] tmp; ptr[2] = &obj3; //----------------------------------------------- ※NULLチェックなどはここでは省いています。

  • int配列をbyte配列に変換

    MIDPアプリを作成している初心者です。 Image データを一旦端末のレコードストアに保存しておく為、 getRGB()で取得したint配列を、byte配列に変換しなくてはいけません。 ↓のように レコードストアに書き込むメソッドを書いてみました。 public void writeRecordStore( String name, Image image ) {     int width = image.getWidth();     int height = image.getHeight();     int[] pxData = new int[ width*height ];     byte[] byteData;     RecordStore rs = null;     try {         //画像をバイトデータに変換         image.getRGB( pxData, 0, width, 0, 0, width, height );         //レコードストアを開く         rs = RecordStore.openRecordStore( name, true );         //バイト配列に変換 ← ここがわからない                  //レコードの追加         rs.addRecord( byteData, 0, byteData.length );              } catch( Exception e ) {     } } int配列をbyte配列に変換する方法わかる方 ご教授の程お願いします。 また、まだコーディングに自信が無いので、文法のミスもご指摘頂けたらありがたいです。

    • ベストアンサー
    • Java
  • クラス内にnewで形成した配列等が含まれる場合

    クラスを関数内に作成した時にそれを実体コピーさせるreturnで返したいんですが、class内newで形成した動的配列があるため、返した後デストラクタが呼ばれるので動的配列の中身が消滅してしまう(させている)のですが、動的配列の消去にデストラクタを使用しないようにするしかありませんか? class a{ public: int *b; a(){b=new int[10];} ~a(){delete b;} //エラー原因 a operator+(a &s){a c;c.b[0] = b[0] + s.b[0];return c;} }; void main() {a x,y;y = x + x;}