2

静的データへのポインターの配列が必要です。例えば

  void func(...) {
     ...
     static int mysize = initial_size;
     static double* d[3] = {new double[mysize], new double[mysize], new double[mysize]};
     for(int i=0; i < 3; ++i) {
        if(cond) {
           //-re-allocate d if necessary.
           use d here;
        }
        else {
           use d here;  //-since d is static; it persists and so this is justified?
        }
     }
     //-Can I get away with not deleting d here??
  }

私の推論は、d は static double へのポインターの配列であるためです。関数内で一度割り当てられるため、すべてが範囲外になると削除されることを願っていますか? 私はどういうわけかそうではないと思います。これはおそらく希望的観測であり、メモリリークにつながりますか?

おそらく、ここで静的 C++ ベクトルを使用したほうがよいでしょうか? ここでは、いくつかの条件が満たされた場合 (たとえば、cond またはその否定などの条件が満たされた場合) に、以前に計算され保存されたデータを d に再利用するために、静的を使用したいと考えています。これが理にかなっていることを願っています。どんなアイデアでも事前に感謝します。

4

3 に答える 3

3

dで割り当てられていないため、削除するとエラーになりますnew。ただし、個々の要素は で割り当てられるnewため、メモリを孤立させないように注意する必要があります。

于 2012-05-24T22:32:46.853 に答える
1

影響はありますが、コードは基本的に問題ありません。

  • purify、insure、valgrind などのメモリ使用量チェック ツールは、メモリ リークの可能性についてより多くのノイズを報告する場合がありますが、それ自体は単なるノイズです。

  • staticスレッド セーフなコードの作成が難しくなります。呼び出し元をd関数パラメーターとして渡すことで、funcスレッド固有のコピー、アプリケーション領域固有のコピー、プロセスを再起動する必要のない簡単な単体テスト、ライフタイムの完全なクライアント コントロールを可能にします。

  • アプリケーションが追加のステージ/フェーズを導入し、呼び出しが終了した後、 func()シャットダウン前に他のメモリ集約型の計算を開始するとします。メモリは引き続き割り当てられます。特に、十分な仮想アドレス空間があり、ディスクにスワップアウトできる場合は問題にならないかもしれませんが、コードが進化するにつれて、メンテナンスの問題が発生する可能性があります。

于 2012-05-25T00:03:58.510 に答える
1

@AdamLiss が上で述べたように、再割り当ての前に既存の配列を慎重に削除しないと、必要に応じて再割り当て dの手順でメモリ リークが発生する可能性があります。

void func(...) {
  static int mysize = initial_size;
  static double* d[3] = {new double[mysize], new double[mysize], new double[mysize]};
  for(int i=0; i < 3; ++i) {
    if(cond) {
      d[i] = new double[2*mysize];  // LEAK!
      use d here;

次のように削除することを覚えていても:

void func(...) {
  static int mysize = initial_size;
  static double* d[3] = {new double[mysize], new double[mysize], new double[mysize]};
  for(int i=0; i < 3; ++i) {
    if(cond) {
      delete[] d[i];
      d[i] = new double[2*mysize];

新しい割り当てが例外をスローし、d[0]削除されたメモリを指している可能性があるため、バグがありますが、それを伝える方法がないため、逆参照された場合に関数が次に呼び出されると、d[0]未定義の動作になります。

これで問題ありません:

void func(...) {
  static int mysize = initial_size;
  static double* d[3] = {new double[mysize], new double[mysize], new double[mysize]};
  for(int i=0; i < 3; ++i) {
    if(cond) {
      double* tmp = new double[2*mysize];
      std::swap(tmp, d[i]);
      delete[] tmp;

ただし、ベクトルを使用して動的メモリを管理すると、このような問題を回避できます。

void func(...) {
  int mysize = initial_size;
  typedef std::vector<double> dvec;
  static dvec d[3] = {dvec(mysize), dvec(mysize), dvec(mysize)};
  for(int i=0; i < 3; ++i) {
    if(cond) {
      //-re-allocate d if necessary.
      d[i].resize(2*mysize);
      use d here;
    }
    else {
      use d here;
    }
  }
}

d[i].size()これには、再割り当て時に古い配列から新しい配列に要素を手動でコピーする必要がなく、既存のサイズを照会できるという利点もあります。

于 2012-05-24T23:09:23.083 に答える