11

私は完全にCの初心者です、私はC#から来ました。私はメモリ管理とmalloc()機能について学びました。私もこのコードに出くわしました:

char *a_persons_name = malloc(sizeof(char) + 2);

私が理解していないのは、これがどのくらいのスペースを割り当てているかですa_persons_name。2文字(例:AB)または他の何かを割り当てていますか?

また、未割り当て領域で「幸運」になり、使用できる場合があることも知っていますmalloc(これにより、データの破損やセグメンテーション違反が発生する可能性があります)。では、割り当てているスペースと必要なスペースをどのように知ることができますか?

4

6 に答える 6

18

そのスニペットは、2文字の名前に十分なスペースを割り当てています。

通常、文字列バッファはどこか、つまりI/Oからいっぱいになります。文字列のサイズが事前にわからない場合(ファイルやキーボードからの読み取りなど)、通常は次の3つの方法のいずれかが使用されます。

  • 任意の文字列の最大サイズを定義し、そのサイズ+ 1(nullターミネータ用)を割り当て、最大でその数の文字を読み取り、指定された文字が多すぎる場合はエラーまたは盲目的に切り捨てます。ひどくユーザーフレンドリーではありません。

  • 段階的に再割り当てし(2次の動作を避けるために、できれば2倍などの等比数列を使用して)、最後に到達するまで読み続けます。コーディングはそれほど簡単ではありません。

  • 固定サイズを割り当て、それを超えないことを望み、この仮定が失敗したときに恐ろしくクラッシュ(または所有)されます。コーディングが簡単で、壊れやすい。たとえばgets、標準Cライブラリを参照してください。(この機能は絶対に使用しないでください。

于 2009-08-08T04:28:51.560 に答える
5

さて、最初sizeof(char)は、常に1なので、malloc(3)

割り当てているものには、3文字分の十分なスペースがあります。ただし、C文字列のヌルターミネータには1つ必要であることに注意してください。

あなたが見つけがちなのは次のようなものです:

#define NAME_SZ 30
: : :
char *name = malloc (NAME_SZ+1);

名前とターミネータ文字のための十分なストレージを取得するため(文字列「xyzzy」は次のようにメモリに格納されることに注意してください:

+---+---+---+---+---+----+
| x | y | z | z | y | \0 |
+---+---+---+---+---+----+

非charベースの配列では、次のように表示されることがあります。

int *intArray = malloc (sizeof (int) * 22);

これにより、22個の整数に十分なスペースが割り当てられます。

于 2009-08-08T04:28:59.843 に答える
3

malloc()はメモリのブロックを割り当て、成功した場合はそのメモリへのポインタを返し、失敗した場合はNULLを返します。メモリのブロックのサイズは、mallocバイト単位の's引数で指定されます。

演算子は、sizeof引数のサイズをバイト単位で指定します。

char *someString = malloc(sizeof(char) * 50)

これにより、NULL文字を含まない49文字の文字列(Cスタイルの文字列はNULL('\0')文字で終了する必要があります)に十分なスペースが割り当てられsomeString、そのメモリをポイントします。

意味がないのでmalloc(sizeof(char) * 2);、質問のコードはである必要があるようです。sizeof(char) + 2

sizeof(char)常に1(バイト)に等しいことが保証されていることに注意してください。ただし、他のタイプ(longなど)のメモリ表現はコンパイラによって異なる場合があります。

動的に割り当てられたメモリで(不)幸運になる方法は、割り当てたメモリの外で読み取り/書き込みを行おうとした場合です。

例えば、

char *someString = malloc(10);
strcpy(someString, "Hello there, world!");
printf("%s\n", someString);

最初の行は、9文字とNULL文字に十分なスペースを割り当てます。
2行目は、20文字(19 + NULL)をそのメモリスペースにコピーしようとします。これによりバッファがオーバーランし、隣接するメモリを上書きしたり、セグメンテーション違反が発生したりするなど、非常に機知に富んだものが発生する可能性があります。

たとえば、someStringのすぐ横にメモリが割り当てられていて、「Hello there、world!」の場合、3行目が機能する可能性があります。そのメモリスペースに遭遇すると、文字列に加えて次のメモリスペースにあるものがすべて出力される可能性があります。その2番目のスペースがNULLで終了した場合、それは停止します-そうでない場合を除きます。そうでない場合は、それはさまよって、最終的にはセグメンテーション違反になります。

この例は非常に単純な操作ですが、間違えるのは簡単です。Cは注意が必要です。注意してください。

于 2009-08-08T04:48:32.050 に答える
1

を呼び出すと、malloc3バイトのメモリが割り当てられます。sizeof(char)は1バイトで、2バイトは明示的に示されます。これにより、サイズ2の文字列(および終了文字)に十分なスペースが与えられます。

于 2009-08-08T04:28:31.203 に答える
1

これにより、3バイトが割り当てられます。sizeof(char)の場合は1、プラス2。その行が文脈から外れているのを見るだけで、なぜそれがそのように割り当てられるのか、またはそれが正しいかどうかを知る方法がありません(私にはそれは怪しいように見えます)。

あなたはそれに入れる必要があるものを保持するのに十分なメモリを割り当てる必要があります。たとえば、文字列を保持するためにメモリを割り当てる場合は、予想される最長の文字列と終了ヌル用の1バイトを保持するのに十分なメモリを割り当てる必要があります。ASCII文字列を扱っている場合、それは簡単です。文字ごとに1バイトと1バイトです。Unicode文字列を使用している場合、状況はさらに複雑になります。

于 2009-08-08T04:31:10.743 に答える
1

最初のポイント-mallocの引数に絶対数を入れないことは良い習慣であり、常にsizeofと倍数を使用します。上記のように、一部のタイプに割り当てられるメモリは、コンパイラとプラットフォームによって異なります。タイプ'blob'の配列に十分なスペースをgettinに保証するには、次のようなものを使用するのが最適です。

blob *p_data = malloc(sizeof(blob) * length_of_array);

このように、タイプが何であれ、メモリ内でどのように見えても、正確に適切な量を取得できます。

第二に、segfaultsなどCは、低水準言語として、境界チェックがありません。これは、実際には配列にないインデックスを見ていることを確認するものが何もないことを意味します。実際、メモリがプログラムに属していない場合でも、メモリへのアクセスを停止することはありません(ただし、オペレーティングシステムは、セグメンテーション違反です)。これが、Cで配列を渡すときはいつでも、その長さも渡す必要がある理由です。これにより、配列を受け取る関数は、配列の大きさを知ることができます。'配列'は実際には最初の要素への単なるポインタであることを忘れないでください。これは、文字列を渡すときに非常に役に立ちません。すべての文字列引数は2つの引数になるため、チートが使用されます。標準のC文字列はすべてNULLで終了します。文字列の最後の文字はASCII値0である必要があります。文字列関数は、それを確認して停止するまで、配列に沿って機能します。このようにして、アレイをオーバーランすることはありませんが、何らかの理由でアレイがオーバーランしない場合は、オーバーランします。それが理解されている

strlen("Hello")

は5ですが、保存するにはもう1文字必要です。例えば:

const char str1 = "Hello";
char *str2 = malloc(sizeof(char) * (strlen(str1) + 1));
strcpy(str2, str1);

はい、sizeof(char)は1と定義されているため不要ですが、より明確であり、間違いなく良い習慣です。

于 2009-08-08T12:41:16.867 に答える