4

次のコードに遭遇しました:

    class a {
    public:

        void *  operator new(size_t l, int nb);
        double  values;
    };
void *a::operator new (size_t l,int n)
{
    return new char[l+ (n>1 ? n - 1 : 0)*sizeof(double)];
}

私が得たものから、それは「値」で始まる構造のような配列を持つために使用されます。

double* Val = &(p->a->values) + fColumnNumber;

私の質問は:メモリリークはありますか?new演算子のオーバーロードは初めてですが、割り当てられたメモリが適切に割り当て解除されていないことは間違いありません。また、スタックに「a」クラスを作成できないということですか?

ありがとう

4

5 に答える 5

5

技術的にはUBをそのまま生成すると思いますが、おそらく目に見える副作用を引き起こすことはないUBの形式です(を使用しnew []ていますが、一致すると思いますdelete-しかしchar、これは通常は発生しません目に見える問題)。

IMO、オブジェクトではなく実際にrawバイトである必要があるものを割り当てるために新しい式を使用していることはほとんど悪いことです。私がそれをしているなら、私はそれを次のように書くでしょう:

void *a::operator new (size_t l,int n)
{
    return ::operator new(l+ (n>1 ? n - 1 : 0)*sizeof(double));
}

あなたはそれを次のものと一致させるでしょう:

void a::operator delete(void *block)
{
    ::operator delete(block);
}
于 2012-05-11T14:29:04.580 に答える
1

operator deleteで呼び出されたデフォルトa *が、このカスタムによって割り当てられたメモリの割り当てを正しく解除できない理由がわかりませんoperator new。確認する最良の方法は、実際にコードを記述して調べることですが、rob05cの手法ではなく、おそらくvalgrindなどのプロファイラーで実行します。質問者はメモリリークが発生しているのを見て、これが原因であると考えているので、この演算子の周りにテストケースを書くことは価値のある努力のように思えます。

後で実際に削除する人がいないと、明らかにリークします...

この種の機能をオーバーライドする必要性については疑問がありますnewが、これは他の誰かのコードだったと思います。

于 2012-05-11T14:12:08.457 に答える
0

見つけるのはかなり簡単です。多くの'を構築および分解するループを作成し、メモリ使用量を監視します。漏れている場合はかなり速く上昇します。

于 2012-05-11T14:08:40.097 に答える
0

そのままでも問題ありませんが、配列を割り当てるときにこのクラスを使用するコードからではdelete[]なく、を使用する必要があります。deleteユーザーはこれを行う必要があるというヒントを受け取らないことに注意してください。そのため、ユーザーの削除演算子をオーバーロードすることをお勧めします。

于 2012-05-11T14:19:55.093 に答える
0
  1. スタック上にクラス「a」を確実に作成できます。
  2. 知っておくべき4つの(実際にはもっと多いが、基本に固執する)new&deleteメソッドシグネチャがあります。

    void* operator new (std::size_t size) throw (std::bad_alloc);
    void* operator new[] (std::size_t size) throw (std::bad_alloc);
    void operator delete (void* ptr) throw ();
    void operator delete[] (void* ptr) throw ();
    

    「operatornew[]」メソッドで実行する必要がある「operatornew」メソッド内に配列を割り当てています。これはあなたの厄介なチェックを取り除きます。「operatornew」と「operatornew[]」の両方を記述します

  3. 呼び出し元にタイプ「a」()のオブジェクトを指定することを忘れないでくださいa myA = new a。したがって、char *ではなく「a」を返すようにしてください。したがって、キャストも行う必要があります。

  4. 対応するdelete[]メソッドとdeleteメソッドを作成する必要があります。

  5. あなたの質問に答えるために、私はそれがメモリをリークすると信じています。あなたが提供した新しい署名は「新しい配置」と呼ばれます。これにより、メモリを割り当てずに新しいポインタを割り当てることができますが、ポイントする場所を指定できます。例:メモリ内の特定のポイントへのポインタが必要な場合。

    long z = 0x0F9877F80078;
    a myA = new (z) a[5];  // 5 pointers that point to 0x0F9877F80078
    

定義上、配置-新しい演算子はメモリを割り当てることは想定されておらず、リークが発生しているためです。2番目の引数を削除します。これは、2つのバージョンの演算子が新しく、準備が整っているため、今すぐ実行できます。オブジェクト「a」を返すことを忘れないでください。

IBMの情報センターをチェックしてください:http: //publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic =%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fcplr318.htm

そして、1つまたは複数のリファレンス、cpluplus.com: http ://www.cplusplus.com/reference/std/new

于 2012-05-11T15:05:03.447 に答える