7

私はこのmalloc関数を研究していて、いくつかのヘルプを使用できます。

static void *malloc(int size)
  {
        void *p;

        if (size < 0)
                 error("Malloc error");
        if (!malloc_ptr)
                 malloc_ptr = free_mem_ptr;

        malloc_ptr = (malloc_ptr + 3) & ~3;     /* Align */

        p = (void *)malloc_ptr;
        malloc_ptr += size;

        if (free_mem_end_ptr && malloc_ptr >= free_mem_end_ptr)
                 error("Out of memory");

        malloc_count++;
        return p;
 }

十分なメモリがある場合、malloc funcは任意のタイプにメモリスペースを割り当てることを知っていますが、私が理解していない行は次のとおりです。

p = (void *)malloc_ptr;
malloc_ptr += size;

そのようなデータ型をどのように指すことができますか?そのvoidポインタまたはその場所を理解できません。

注:malloc_ptrはunsignedlongです

4

5 に答える 5

7

void ポインターを返す理由は、malloc呼び出しで何にスペースを割り当てているのかがわからないためです。それが知っているのは、あなたが要求したスペースの量だけです。メモリを埋めるものを決定するのは、あなたまたはあなたのコンパイラ次第です。void ポインターの位置は、通常、整合性を維持し、メモリのどの値が解放されているかを知るために、リンクされたリストとして実装されます。これは、free関数で驚くほど追跡されます。

于 2012-12-25T19:28:00.613 に答える
3

これは の実装mallocあるため、通常のプログラムでは正当化されないことを行うことができます。unsigned long具体的には、 からへの実装定義の変換を利用していvoid *ます。プログラムの初期化は、割り当てられていないメモリの大きなブロックの数値アドレスmalloc_ptrに設定されます。次に、割り当てを要求すると、現在の値からポインターが作成され、要求したバイト数だけ増加します。そうすれば、次に呼び出すときに新しいポインターが返されます。mallocmalloc_ptrmalloc_ptrmalloc

これは、 の最も単純な実装に関するものmallocです。最も注目すべきは、解放されたメモリを再利用しないように見えることです。

于 2012-12-25T19:31:25.677 に答える
2
 p = (void *)malloc_ptr;

mallocこれは、データ型が不明な領域へのポインターであることを示します。強力な型システムのため、キャストの使用は C++ でのみ必要ですが、C ではそうではありません。malloc一部のプログラマーによると、特定のポインター型が返されないことは型安全でない動作です。

mallocタイプではなくバイト数に基づいて割り当てます。

 malloc_ptr += size;

C は from および tovoid*に暗黙的にキャストするため、キャストは自動的に行われます。C++ では、 への変換のみvoid*が暗黙的に行われ、他の方向には明示的なキャストが必要です。

型キャストに関するWikiの説明: mallocfunction は、型指定されていないポインター型void *を返します。これは、呼び出し元のコードが適切なポインター型にキャストする必要があります。古い C 仕様では、そうするために明示的なキャストが必要だったので、コードは

(struct foo *) malloc(sizeof(struct foo))

慣習として受け入れられるようになりました。

ただし、この方法は ANSI C では推奨されていません。これmallocは、定義されているヘッダー ファイルをインクルードする際の失敗を隠すことができるためです。その結果、int 型とポインター型のサイズが異なるマシン (現在はどこにでもある x86_64 アーキテクチャーなど) でダウンストリーム エラーが発生します。 . C++ としてコンパイルする必要があるコードでは、その言語でキャストが必要なため、競合が発生します。

于 2012-12-25T19:44:33.960 に答える
2

Malloc は、完全に構造化されていないフラットなメモリのチャンクへのポインタを返しています。(void *) ポインターは、それが何を指しているのか (構造がない) がわからないことを意味し、サイズ size のメモリを指しているだけです。

malloc への呼び出しの外で、このポインターが何らかの構造を持っていることをプログラムに伝えることができます。つまり、構造がある場合は、次のようにsome_struct言うことができます struct some_struct *pStruct = (struct some_struct *) malloc(sizeof(struct some_struct))

malloc が割り当てようとしているもののサイズだけを知っていて、実際にはその構造を知らないことがわかりますか? malloc への呼び出しは、構造に関する情報を渡さず、割り当てるメモリのサイズのみを渡します。

これが C の一般的な方法です。malloc は一定量のメモリを返し、それを必要な構造化メモリにキャストするのはあなたの仕事です。

于 2012-12-25T19:30:05.930 に答える
1

この両方の行を見ると、

p = (void *)malloc_ptr;
malloc_ptr += size;

ここでは unsigned long 型の malloc_ptr を使用しているため、この変数を void 型にキャストしてから p に格納します。同様に、2 つ目は malloc_ptr = malloc_ptr + size; を示しています。

p は void ポインター型であるため、この両方のコードは開発者の快適さのためのものです。そのため、アプリケーションで malloc を使用すると、関数によって返される必要があるメモリ ブロックの型がわからないため、この関数は常にこの一般的な void ポインターを返すので、要件に従って、アプリケーションで再度型キャストすることができます。

サイズを負で入力した場合、2番目のコードでも同じです。この条件で何が起こるか

if (free_mem_end_ptr && malloc_ptr >= free_mem_end_ptr)
error("Out of memory");
于 2012-12-27T16:02:21.690 に答える