web-dev-qa-db-ja.com

<stdlib.h>と<malloc.h>の違い

Cプログラムでmallocを使用すると、警告が表示されます。

warning: incompatible implicit declaration of built-in function 'malloc' [enabled by default]

<malloc.h>または<stdlib.h>をインクルードして、warningを削除できますが、それがなくても機能します。

だから、これらのヘッダーと、何も含めないときにgccリンクとの違いは何ですか?

ubuntu 12.04 64-bitgcc 4.6.3を使用しています)

40
none

<malloc.h>ヘッダーは非推奨です(そして、非常にLinux固有で、 mallinfo(3) のような非標準関数を定義します)。 malloc(3) と関連する標準関数(例:freecallocrealloc ..が必要な場合は、代わりに<stdlib.h>を使用してください。 ..)。 <stdlib.h>C89 (およびそれ以降)標準で定義されていますが、<malloc.h>では定義されていないことに注意してください。

/usr/include/malloc.hを調べると、malloc....に加えて、いくつかの非標準関数(たとえば malloc_stats(3) など)が見つかります。

また、gccはヘッダーファイルをリンクせず、ライブラリをリンクします。 リンカーとローダー に関するLevineの本を読んでください。

ヘッダーを含めない場合(およびmallocを自分で明示的に宣言しないでください。これは悪い考えです)、mallocint値を返すと暗黙的に宣言されます(これは間違っている)。使用する際には、少なくとも-Wallフラグをgccに渡すようにしてください。

-vgccに渡して、関連する実際のプログラムを理解することもできます。cc1はコンパイラ固有(アセンブリコードを生成)、asはアセンブラ、ldリンカー、および collect2 リンカーを呼び出す内部ユーティリティ。

49

stdlib.hは、特にmalloc()、calloc()、free()関数を宣言する標準Cヘッダーです。これは、含める必要のあるヘッダーです。

malloc.hは非標準ヘッダーであり、多くのシステムで見られます。多くのシステムでは、そのプラットフォームで使用されるmalloc実装に固有の追加機能を定義することがよくあります。

これらのいずれも含まない場合、デフォルトはありませんが、malloc関数の事前宣言なしでmalloc()を呼び出すと、Cは関数プロトタイプがint malloc();であると想定しますが、これはしばしば間違っています。ヘッダーに加えて、Cコンパイラは通常、標準ライブラリにリンクします。 Linux上のglibc。mallocの実装が存在します。

ヘッダーファイルとライブラリには違いがあることに注意してください。ヘッダーファイルは、構造体や関数プロトタイプなどを宣言します。ライブラリには、実装、コンパイル済みコードが含まれます。ライブラリにリンクし、ヘッダーファイルを#includeします。

9
nos

ヘッダーは異なる関数セットを宣言しますが、両方ともmallocを前方宣言します。

どちらも含めない場合、mallocのプロトタイプがないため、警告が表示されます。ただし、malloc関数は1つしかないため、同じ関数に対してリンクします。 2つの場所で前方宣言されているだけです。前方宣言はmalloc関数にリンクするのに役立つものではなく、コンパイラが呼び出しの周りに正しいコードを発行して引数を指定し、戻り値を読み取ることができるようにするためのものです。

<malloc.h>は標準のインクルードではないことに注意してください。 GCCでstdlib.hmalloc.hが含まれることはないと思いますが、それが必要な宣言を提供する1つの方法なので、そうなると想像できます。

6
Steve Jessop

_<malloc.h>_は標準ヘッダーではないため、移植できません。標準ではmalloc() et al。 _<stdlib.h>_で。

3
aib

他の人はすでに<malloc.h>と<stdlib.h>の違いについて議論しています

どちらも含まれていない場合の警告については、それがC関数の動作の定義です。プロトタイプのない関数(自分で宣言せず、ヘッダーを含めない場合)は、int戻り値型とを持つ関数として扱われます指定なし引数リスト。

コンパイラーはデフォルトのプロモーション(例えば、float to doubleなど)を実行し、関数が呼び出されます。関数で使用される引数の数が渡された数と異なる場合、またはデフォルトの昇格後の引数タイプが関数の実装と互換性がない場合、それは未定義の動作です。

ISO 9899:1999(C99)§6.5.2.2、¶6を参照してください:

呼び出された関数を示す式の型がプロトタイプを含まない場合、整数のプロモーションは各引数で実行され、タイプfloatの引数はdoubleに昇格されます。これらはデフォルト引数プロモーションと呼ばれます。引数の数がパラメーターの数と等しくない場合、動作は未定義です。関数がプロトタイプを含む型で定義され、プロトタイプが省略記号(、...)で終わるか、昇格後の引数の型がパラメーターの型と互換性がない場合、動作は未定義です。関数がプロトタイプを含まない型で定義され、昇格後の引数の型が昇格後のパラメーターの型と互換性がない場合、次の場合を除き、動作は未定義です。

  • 一方の昇格型は符号付き整数型であり、もう一方の昇格型は対応する符号なし整数型であり、値は両方の型で表現可能です。
  • 両方のタイプは、文字タイプまたはvoidの修飾バージョンまたは非修飾バージョンへのポインターです。

プロトタイプなしでmalloc()を呼び出す場合、これは非常に悪い可能性があります。 malloc()は、size_t引数を受け入れ、void *ポインターを返します。整数引数のデフォルトの昇格の結果、size_tとは異なるサイズの整数が生成される場合、未定義の動作が発生します。 intのサイズがvoid *と異なる場合(たとえば、intは32ビットで、void *は64ビットになる64ビットシステムの場合、 )返されたポインターは台無しになります。

2
David C.

違いを知るには、その内容を自分で読んでください。

デフォルトでは、gccはどちらも読み取りません。

それらを読むと、mallocの宣言が異なることがわかります。

1
bmargulies