6

重複の可能性:
(POD)メモリの解放:delete []はdeleteと同じですか?

delete配列の最初の要素を超えて要素の割り当てを解除しますか?

char *s = new char[n];
delete s;

上記の場合、のすべての要素が連続して割り当てられていることを確認することは重要であり、配列の一部のみsに割り当てられるべきではありませんか?delete

より複雑なタイプの場合delete、最初のオブジェクトを超えてオブジェクトのデストラクタを呼び出しますか?

Object *p = new Object[n];
delete p;

最初の数を超えるsの数をどのようdelete[]に推測できObjectますか?これは、割り当てられたメモリ領域のサイズを認識している必要があるという意味ではありませんか?パフォーマンス上の理由でメモリ領域にオーバーハングが割り当てられた場合はどうなりますか?たとえば、すべてのアロケータが1バイトの粒度を提供するわけではないと想定できます。その場合、特定の割り当ては、要素全体またはそれ以上、各要素に必要なサイズを超える可能性があります。

、などのプリミティブ型の場合、次の間にchar違いintはありますか。

int *p = new int[n];
delete p;
delete[] p;
free p;

delete->free割り当て解除機構を介してそれぞれの呼び出しがたどるルートを除いて?

4

10 に答える 10

16

これは未定義の動作であり(ヒープが破損したり、プログラムがすぐにクラッシュしたりする可能性があります)、絶対に実行しないでください。そのメモリの割り当てに使用されたものに対応するプリミティブを持つメモリのみを解放します。

このルールに違反すると、偶然に適切に機能する可能性がありますが、コンパイラ、ランタイム、コンパイラ設定などの変更が行われると、プログラムが破損する可能性があります。あなたはそのような適切な機能に決して頼ってそれを期待するべきではありません。

delete[]要素の数を決定するためにコンパイラ固有のサービスデータを使用します。通常、が呼び出されると、より大きなブロックが割り当てられnew[]、番号は最初に保存され、発信者には保存された番号の後ろのアドレスが与えられます。とにかく、他のものではなく、delete[]によって割り当てられているブロックに依存していnew[]ます。と以外new[]のものをペアリングする場合、delete[]またはその逆の場合、未定義の動作に遭遇します。

于 2009-10-23T08:19:13.523 に答える
10

FAQを読んでください:16.3 newで割り当てられたfree()ポインタはありますか?malloc()で割り当てられたポインタを削除できますか?

上記の場合、sのすべての要素が連続して割り当てられており、配列の一部のみを削除することはできないはずなので、重要ですか?

はい、そうです。

delete []は、最初のオブジェクトを超えるオブジェクトの数をどのように推測できますか?これは、割り当てられたメモリ領域のサイズを認識している必要があることを意味しませんか?

コンパイラは知る必要があります。FAQ16.11を参照してください

コンパイラがその情報を保存するからです。

つまり、コンパイラはdelete適切な簿記コードを生成するために異なるを必要とします。これが今はっきりしていることを願っています。

于 2009-10-23T08:19:17.813 に答える
4

はい、これは危険です!

やめろ!

プログラムのクラッシュやさらに悪い動作につながります!

割り当てられたオブジェクトには、;を使用するnew必要があります。delete

割り当てられたオブジェクトには、;を使用するnew []必要があります。delete []

で割り当てられたオブジェクトの場合、malloc()または使用するcalloc()必要がありfree()ます;

これらすべての場合において、すでに削除/解放されたポインタをもう一度削除/解放することは違法であることに注意してください。freenullで呼び出されない場合もあります。delete/delete[]NULLでの呼び出しは有効です。

于 2009-10-23T08:30:51.707 に答える
3

はい、実際には危険が伴います。operator new/operator delete実装の詳細はさておき、operator new[]/operator delete[]関数は完全に独立して置き換えることができることを忘れないでください。このため、、などを、まったく共通点のない、完全に独立した異なるメモリ割り当て方法と考えるのが賢明new/deleteです。new[]/delete[]malloc/free

于 2009-10-23T08:47:06.867 に答える
2

削除は、配列の最初の要素を超えて要素の割り当てを解除しますか?

いいえ。deleteは、これを行うコンパイラに関係なく、最初の要素のみの割り当てを解除します。場合によっては機能するかもしれませんが、それは偶然です。

上記の場合、sのすべての要素が連続して割り当てられており、配列の一部のみを削除することはできないはずなので、重要ですか?

メモリがどのように空きとしてマークされているかによって異なります。ここでも実装に依存します。

より複雑なタイプの場合、deleteは最初のオブジェクト以外のオブジェクトのデストラクタを呼び出しますか?

いいえ。これを試してください:

#include <cstdio>

class DelTest {
    static int next;
    int i;
public:
    DelTest() : i(next++) { printf("Allocated %d\n", i); }
    ~DelTest(){ printf("Deleted %d\n", i); }
};

int DelTest::next = 0;

int main(){
    DelTest *p = new DelTest[5];
    delete p;
    return 0;
}

delete []は、最初のオブジェクトを超えるオブジェクトの数をどのように推測できますか?これは、割り当てられたメモリ領域のサイズを認識している必要があることを意味しませんか?

はい、サイズはどこかに保存されています。保存場所は実装によって異なります。たとえば、アロケータは、割り当てられたアドレスの前のヘッダーにサイズを格納できます。

パフォーマンス上の理由でメモリ領域にオーバーハングが割り当てられた場合はどうなりますか?たとえば、すべてのアロケータが1バイトの粒度を提供するわけではないと想定できます。その場合、特定の割り当ては、要素全体またはそれ以上、各要素に必要なサイズを超える可能性があります。

このため、返されるアドレスはワード境界に揃えられます。「オーバーハング」は、sizeof演算子を使用して確認でき、スタック上のオブジェクトにも適用されます。

char、intなどのプリミティブ型の場合、...の間に違いはありますか?

はい。mallocとnewは、別々のメモリブロックを使用している可能性があります。そうでない場合でも、それらが同じであると想定しないことをお勧めします。

于 2009-10-23T08:54:31.923 に答える
2

Raymond Chen(Microsoft開発者)は、スケーラーとベクトルの削除について詳しく説明し、違いの背景を説明しています。見る:

http://blogs.msdn.com/oldnewthing/archive/2004/02/03/66660.aspx

于 2009-10-23T13:43:38.553 に答える
1

char、intなどのプリミティブ型の場合、次の間に違いはありますか。

未定義の動作が発生すると思います。したがって、安定した動作を期待するべきではありません。常にnew/delete、new [] / delete []、malloc/freeのペアを使用する必要があります。

于 2009-10-23T08:17:35.353 に答える
1

これは未定義の動作です。したがって、答えは次のとおりです。はい、危険がある可能性があります。そして、何が問題を引き起こすのかを正確に予測することは不可能です。一度は効いたとしても、また効くのでしょうか?タイプによって異なりますか?要素数?

于 2009-10-23T08:17:58.567 に答える
0

論理的には、delete[]の代わりにnew[]とfreeまたはdeleteを混在させることができるように見えるかもしれませんが、これは、コンパイラがかなり単純である、つまり、実装に常にmalloc()を使用するという前提の下にあります。 new[]のメモリ割り当て。

問題は、コンパイラに十分に賢いオプティマイザがある場合、作成したオブジェクトのnew[]に対応する「delete[]」がないことを確認する可能性があることです。したがって、new []の実際のmalloc()を呼び出すコストを節約するために、スタックを含むどこからでもメモリをフェッチできると想定する場合があります。次に、free()を呼び出そうとしたり、間違った種類の削除を実行しようとすると、誤動作が発生する可能性があります。

于 2009-10-23T08:48:27.053 に答える
0

ステップ1これを読んでください:what-is-the-difference-between-new-delete-and-malloc-free

あなたは開発者側で見ているものだけを見ています。
考慮していないのは、stdlibがメモリ管理を行う方法です。

最初の違いは、newとmallocがメモリ内の2つの異なる領域からmemroyを割り当てることです(FreeStoreからのNewとHeapからのmalloc(どちらも基本的にヒープである名前に焦点を当てないでください。これらは標準からの正式な名前です))。一方から割り当て、もう一方に割り当てを解除すると、メモリの管理に使用されるデータ構造が台無しになります(メモリ管理に同じ構造を使用するという保証はありません)。

このようにブロックを割り当てる場合:

int*   x= new int; // 0x32

記憶はこのように見えるかもしれません:私がそれほど一生懸命考えずにこれを作ったので、それはおそらくないでしょう。

Memory   Value      Comment
0x08     0x40       // Chunk Size  
0x16     0x10000008 // Free list for Chunk size 40
0x24     0x08       // Block Size
0x32     ??         // Address returned by New.
0x40     0x08       // Pointer back to head block.
0x48     0x0x32     // Link to next item in a chain of somthing.

重要なのは、割り当てられたブロックには、メモリ管理を処理するために割り当てたintだけでなく、はるかに多くの情報があるということです。

この標準では、(C / C ++スタイルで)コンパイラ/ライブラリの製造元がアーキテクチャに最も効率的なメモリ管理方法を実装する能力に影響を与えたくないため、これがどのように行われるかを指定していません。

これを考慮に入れて、アレイの割り当て/割り当て解除を通常の割り当て/割り当て解除と区別できるようにし、両方のタイプで独立して可能な限り効率的にすることができるようにする必要があります。その結果、内部的に異なるデータ構造を使用する可能性があるため、混合して一致させることはできません。

CアプリケーションとC++アプリケーションのメモリ割り当ての違いを実際に分析すると、それらが大きく異なることがわかります。したがって、アプリケーションの種類に合わせて最適化するために、まったく異なるメモリ管理手法を使用することは不合理ではありません。これは、おそらくより効率的であるため、C ++でmalloc()よりもnewを好むもう1つの理由です(ただし、より重要な理由は、常に複雑さ(IMO)を減らすことです)。

于 2009-10-23T19:28:38.903 に答える