malloc関数の詳細とnewとの違い


今日偶然1つの面接の経験の中でmallocとnewの違いに言及することを見て、突然自分が2つすべて使ったことがあることを発見して、しかし違いについて、本当によく分からないで、だからいくつかの資料をよく調べて、この点に対して徹底的に理解して、今私の学んだ記録を下ります.
mallocとfreeはC++/C言語の標準ライブラリ関数であり、new/deleteはC++の演算子である.ダイナミックメモリの申請やメモリの解放に使用できます.
1.malloc関数の初期プローブ
まず、mallocは関数であり、mallocのフルネームはmemory allocationであり、中国語では動的メモリ割り当てと呼ばれていることを知っておく必要があります.モデルは次のとおりです.
void *malloc(int size);

説明:mallocはsizeバイトを指定したメモリ領域をシステムに割り当て、戻りタイプはvoid*タイプです.void*は、未確定タイプのポインタを表します.C,C++はvoid*タイプが他のタイプのポインタに強制的に変換できることを規定している.ここで注意:(1)void*は、未確定タイプのポインタを表し、より明確には、メモリ領域を申請する際にユーザがこの空間でどのタイプのデータを格納しているのか(例えばcharかintか...)(2)mallocを使用してシステムにメモリを申請する際に割り当てに失敗する可能性があることを意味する.割り当てに失敗した場合は、空のポインタ(NULL)が返されます.分配失敗の原因については,空間不足が一つであるなど,多くの種類がある.対応するメモリを解放する関数:
void free(void *FirstByte);

この関数は、mallocで割り当てられた空間をプログラムやオペレーティングシステムに返します.つまり、このメモリを解放して、再び自由にします.使い方については、実はこの2つの関数を使うのは難しくありません.つまりmalloc()の後、free()に解放する必要はないと思います.簡単な例を挙げます.
char *Ptr = NULL; 
Ptr = (char *)malloc(100 * sizeof(char)); 
if (NULL == Ptr){ 
        exit (1); 
} 
gets(Ptr);  
free(Ptr); 
Ptr = NULL; 

もちろん、具体的な状況は具体的に分析し、具体的に解決しなければならない.たとえば、ポインタを定義し、1つの関数でメモリを申請して関数を介してこのポインタに返すと、このメモリを解放する作業は他の関数に残すべきかもしれません.各malloc()の後にfree()が対応しなければならないことを保証します.
この関数の使い方について注意すべき点は、次のとおりです.
1.メモリ容量を申請した後、割り当てに成功したかどうかを確認する必要があります.
2.申請したメモリを再使用する必要がない場合は、解放してください.リリース後、このメモリへのポインタをNULLに向けるべきで、プログラムの後ろでうっかり使用しないようにします.
3.この2つの関数はペアリングであるべきです.申請後に解放されなければメモリが漏洩します.理由もなく釈放されたら何もしなかった.リリースは1回のみで、2回以上リリースするとエラーが発生します(空のポインタをリリースするのは例外ですが、空のポインタをリリースするのは実は何もしていないのと同じなので、空のポインタをリリースして何度もリリースしても問題ありません).
4.malloc()関数のタイプはvoid*であり、任意のタイプのポインタはvoid*に変換できますが、コンパイラのチェックを避けるため、前に強制タイプ変換を行うことが望ましいです.
2.malloc関数の詳細
以上の内容を見て、malloc関数の初歩的な内容とその使い方を大体知っていますが、malloc関数がどのように動的にメモリを割り当てるか分かりません.どうやってメモリを動的に割り当てますか?
答えは山の中から空間を得ることです.つまり、関数が返すポインタは、スタック内のメモリを指します.オペレーティングシステムには、空きメモリアドレスを記録するチェーンテーブルがあります.オペレーティングシステムがプログラムの申請を受信すると、チェーンテーブルを巡回し、申請された空間よりも大きな最初の空間のスタックノードを探し、そのノードを空きノードチェーンテーブルから削除し、そのノードの空間をプログラムに割り当てます.
ここまで言うと積み上げざるを得ませんが、何が積み上げられているのでしょうか.スタックはみんなが共有する空間で、グローバルスタックとローカルスタックに分かれています.グローバル・スタックは割り当てられていないすべての空間であり、ローカル・スタックはユーザーが割り当てた空間である.スタックはオペレーティングシステムがプロセスを初期化するときに割り当てられ、実行中にシステムに追加のスタックを要求することもできます.スタックから申請したメモリが切れたらオペレーティングシステムに返す、つまり解放し、返さないとメモリ漏れが発生することを覚えておいてください.
メモリ漏洩とは、あなたが食堂に行って食事をしているようなもので、あなたが食べ終わった後、皿を持って行かなかったのは、他の人から見ればこの席に人が占めているように見えます.恐ろしいことに、あなたが振り返って食事をしてまた新しい席を占めています.あなたが食べ終わった後も皿を持って行かなかったのです.ついに、食堂全体の席がいっぱいになって、食堂も散らかっていました.(比喩はあまり適切ではありませんが、大体この意味です)
普段私たちはいつもスタック、スタックと言っていますが、そのスタックは何ですか.スタックはスレッド固有で、実行状態とローカル自動変数を保存します.スタックはスレッドの開始時に初期化され、各スレッドのスタックは互いに独立している.各関数には独自のスタックがあり、スタックは関数間でパラメータを渡すために使用されます.オペレーティングシステムがスレッドを切り替えるときに自動的にスタックを切り替えるのは、SS/ESPレジスタを切り替えることです.スタックスペースは、高度な言語で明示的に割り当てられ、解放される必要はありません.
上記の概念の説明から、以下のことがわかります.
スタックは、コンパイラによって自動的に割り当てられて解放され、関数のパラメータ値、ローカル変数の値などが格納されます.動作は、データ構造内のスタックに似ています.
スタックは一般的にプログラマによって解放され、解放されなければ、プログラムの終了時にオペレーティングシステムによって回収される可能性があります.ここに注意するのは可能だが、必ずしもそうではない.だから山は必ず解放しなければならない!
3.new演算子
3.1 C++では、newとdeleteで配列または単一オブジェクトを動的に作成および解放します.オブジェクトを動的に作成する場合は、そのデータ型を指定するだけで、そのオブジェクトに名前を付ける必要はありません.new式は、新しい作成オブジェクトを指すポインタを返します.ポインタでオブジェクトに問い合わせることができます.
int *pi=new int;

このnew式は、スタック領域に割り当てられて整数オブジェクトを作成し、そのオブジェクトのアドレスを返し、ポインタpiを初期化します.
3.2動的作成オブジェクトの初期化
動的に作成されたオブジェクトは、変数を初期化する方法で初期化できます.
int *pi=new int(100); //  pi          100
string *ps=new string(10,'9');//*ps  “9999999999”

表示初期化が指定されていない場合は、クラスタイプに対して、そのクラスのデフォルト構造関数で初期化します.組み込みタイプのオブジェクトは初期化されていません.動的に作成されたオブジェクトの値を初期化することもできます.
int *pi=new int( );//    0
int *pi=new int;//pi           int
string *ps=new string( );//         (               ,              )

3.3動的に作成されたオブジェクトdelete式の解除ポインタが指すアドレス空間.
delete pi ;//       
delete [ ]pi;//    

ポインタがnewで割り当てられたメモリアドレスでない場合、deleteを使用するのは合法ではありません.
3.4 deleteの後、ポインタの値をリセットする
delete p; 

この文を実行すると、pは不確定なポインタとなり、多くのマシンでは、p値が明確に定義されていないにもかかわらず、以前に指すオブジェクトのアドレスが格納され、pが指すメモリが解放されるため、pは有効ではありません.このとき、ポインタはサスペンションポインタになります(サスペンションポインタは、オブジェクトが格納されていたメモリを指しますが、オブジェクトは既に存在しません).サスペンションポインタは往々にしてプログラムエラーを引き起こし、検出しにくい.ポインタが指すオブジェクトを削除すると、すぐにポインタを0に設定します.これにより、ポインタがオブジェクトを指さないことが明らかになります.(ゼロ値ポインタ:int *ip=0;)
3.5ゼロポインタとNULLポインタの区別
ゼロ値ポインタは、値が0のポインタであり、任意のポインタタイプであってもよく、汎用変形タイプvoid*であってもchar*、int*であってもよい.空のポインタ、実は空のポインタはただ1種のプログラミングの概念で、1つの容器が空と非空の2種類の基本的な状態があるかもしれないようで、空ではない時に中に1つの数値が0であることを格納したかもしれないので、空のポインタは人為的に考えているポインタでアドレスのメッセージを提供しません.
4.mallocとnewの違い
(1)newは、指定したタイプのポインタを返し、必要なサイズを自動的に計算することができる.mallocは、バイト数を計算し、戻った後に実際のタイプのポインタに強制的に変換する必要があります.例:
//new
int *p;   
p = new int; //     int*   (     ),      sizeof(int); 
int* parr;   
parr = new int [100]; //      int*   (     ),     sizeof(int) * 100;

//malloc
int* p;   
p = (int *) malloc (sizeof(int)*128);//  128 (            )      ,   128                     p  
double *pd=(double *) malloc (sizeof(double)*12);//  12 double     ,            pd 

(2)mallocはメモリを割り当てるだけで,得られたメモリを初期化することはできないので,得られた新しいメモリのうち,その値はランダムになる.Newで作成したオブジェクトは変数を初期化することで初期化できます.
割り当ておよび最終解放の方法が異なる以外はmallocまたはnewによりポインタが得られ,他の操作で一致したままである.
5.参考資料
1.C++Primer 2.C++のnew/deleteとnew[]/delete[]について簡単に説明します.新とmallocの違いを深く解析する.malloc/freeとnew/deleteの違い5.Cのmallocとfree 6について簡単に述べる.malloc関数の詳細