2012-12-25 11 views
5

私はこのmalloc関数を勉強していると私はいくつかの助けを使用することができます。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は、それはそれはあなたがmalloc通話中のためのスペースを割り当てているかわかりませんので、あるのvoidポインタを返すunsigned long型

+0

このコードで何が起こるのか、その後マイナスにサイズを入力している場合には、第2のコードで同じ符号なしlong' 'へのポインタが(つまり' malloc_ptr')も指すことができるという仮定が含まれていますアラインメントの観点から、他のどのオブジェクトにも適用できます。この仮定は必ずしも正しいとは限りません(例えば、いくつかのシステムでは 'long double'オブジェクトを指すことができないかもしれません)。 –

+0

コードでは、4バイトアライメントよりも厳密なアラインメント要件を持つタイプはないものとしています。このコードは 'free_mem_ptr'と' free_mem_end_ptr'の初期化方法を示していません。スペースがなくなるとNULLを返しません。関数 'error()'が返ってくると、すべての地獄が緩んでしまいます。 –

答えて

5

理由です。それが知っているのはあなたが要求したスペースの量だけです。メモリを満たすものを決めるのは、あなたやコンパイラに任されます。ボイドポインタの位置は、通常、整合性を維持し、メモリのどの値が無料であるかを知るためのリンクリストとして実装されており、驚くことにはfree機能で追跡されます。

+0

しかし、どのくらいのスペースを割り当てるかは分かりますか?サイズの値はどのように使用されますか?私はそれを見ない。例えば、私はstruct mystructと呼ばれる8 ints 3 charsと1 floatを持っており、理論的にそれは多くのメモリスペースを割り当てる必要がありますが、私はちょうど理解できません – morcillo

+0

@morcilloその場合はおそらく ' sizeof'演算子は、宣言した構造体を適切に割り当てるために必要なバイト単位の正しいサイズを決定します。 – squiguy

+0

私はsizeofがそのためであることを知っていますが、私が理解していないことは、メモリ内にスペースを割り当てる方法です。 malloc_ptrは型のサイズを持っていますが、p =(void *)のmalloc_ptrは8バイト、2バイト、または152バイトをどのように割り当てるかを知っていますか?それを動作させるmalloc関数へのキャストですか? (my_struct *)malloc(sizeof(my_struct))?? – morcillo

1

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

mallocの呼び出しの外に、このポインタに構造体があることをプログラムに伝えることができます。つまり、構造がある場合some_structと言うことができます:。

mallocは割り当てようとしているもののサイズしか知りませんが、実際にその構造を認識していないのを見てください。 mallocへの呼び出しでは、構造体に関する情報は渡されません。割り当てられるメモリの量だけです。

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

1

これはの実装mallocです。したがって、通常のプログラムでは正当ではないことが許可されています。具体的には、unsigned longからvoid *への実装定義の変換を利用しています。プログラムの初期化では、がの数値アドレスに割り当てられていません。次に、割り当てを要求すると、mallocは現在の値malloc_ptrからポインタを作成し、要求したバイト数でmalloc_ptrを増やします。そうすれば、次回にmallocと呼ぶと新しいポインタが返されます。

これは、mallocの最も簡単な実装についてです。最も顕著なのは、解放されたメモリを再利用することではないようです。あなたは、この両方の行を見たよう

1
p = (void *)malloc_ptr; 

`malloc` returns a void pointer, which indicates that it is a pointer to a region of 
unknown data type. The use of casting is only required in C++ due to the strong type 
system, whereas this is not the case in C. The lack of a specific pointer type 
returned from `malloc` is `type-unsafe` behaviour according to some programmers: 
malloc allocates based on byte count but not on type. 

malloc_ptr += size; 

`C` implicitly casts from and to `void*`, so the cast will be done automatically. In 
`C++` only conversion to void* would be done implicitly, for the other direction an 
explicit cast is required. 

Wiki型鋳造についての説明、

`malloc` function returns an untyped pointer type `void *`, which the calling code must 
cast to the appropriate pointer type. Older C specifications required an explicit cast 
to do so, therefore the code `(struct foo *) malloc(sizeof(struct foo))` became the 
accepted practice. However, this practice is discouraged in ANSI C as it can mask a 
failure to include the header file in which `malloc` is defined, resulting in 
downstream errors on machines where the int and pointer types are of different sizes, 
such as the now-ubiquitous x86_64 architecture. A conflict arises in code that is 
required to compile as C++, since the cast is necessary in that language. 
1

、unsigned型の

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

あなたが持っているmalloc_ptrは長いので、型キャストこの変数ですvoid型に変換し、pに格納します。 と同様に、2番目のものはmalloc_ptr = malloc_ptr + sizeを意味します。

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

、あなたはこの条件

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