1

次のコードを書いたとき、奇妙な答えが得られました。

#include<stdio.h>
#include<stdlib.h>
main()
{
int *p=malloc(1);
if(p==0)
printf("memory not assigned\n");
else
{
printf("memory assigned\n");
printf("enter an int\t");
scanf("%d",p);
printf("\n You entered number %d",*p);
printf("\nIt has been stored at-%p",p);
}
}

malloc はバイト数として引数を取ると思うので、ここで 1 バイトを入力し、私のマシンでは int が (sizeof() を介して) ストレージに 4 バイトを必要とすることを知っていますが、それでもコードはエラーを表示せず、int 値を入力できます。 3333333 と入力しても問題はありません。malloc(1) の代わりに malloc() を使用すると、gcc は malloc の引数が少なすぎると不平を言いますが、それでも同じ結果が得られます。

仮想ボックスを介してgccで実行しています。

4

5 に答える 5

3

あなたが言ったように、あなたがこれをするならば:

int *p=malloc(1);

1バイトのみが割り当てられます。intは1バイトより大きいため、割り当てられたメモリをオーバーランし、未定義の動作を提供します。これを行う場合:

int *p=malloc(sizeof(int));

次に、整数のための十分なスペースがあります。

Cは、割り当てられたメモリの範囲外で実行しても警告を表示しないため、mallocのサイズを慎重に管理する必要があります。

于 2013-03-01T05:46:08.987 に答える
2

「現代的な」環境の Malloc は、異なる長さに対して異なる種類の割り当て戦略を使用します。共通することは、32 ビット環境では、デファクト スタンダードはすべてを 8 バイト単位で整列することであり、現在の x64 時代では 16 バイトの粒度で整列することでした。

これは実際には、要求した 1 バイトの後に 7 文字または 15 文字の余分なスペースがあることを意味します。あなたはそれを使うべきですか?密室で同意した大人とのみ。

メソッドの中には、ところで、物理的な境界でページを割り当てるシステム コールに戻すものがあります。たとえば、malloc(1<<28); を試してください。(256 メガバイト); malloc の一部の実装では、特別なバッファーから 1 ~ 8 または 1 ~ 16 バイトを割り当て、さらに大きなチャンクの場合は、ブックキーピング データ用に N+8 または N+16 (これも次の境界に切り上げられます) を内部的に予約します。

これは、予約領域を上書きすると破棄されるデータです。後でいくつかのmalloc / freeでASSERTにつながり、重複してすぐに閉じられるSOに関する非常に漠然とした質問につながります。

組み込みシステムの malloc は、再利用できないようにプログラムできます。それは単に実装することができます

void *malloc_embedded(size_t a) {
    static uint8_t *heap=_heap;
    uint8_t *old=heap; heap+=a;
    return old;
}

これはおそらく予想どおりに動作しますが、使用例ははるかに限られています。このメソッドを変更して、最後に割り当てられた要素を解放できるようにすることもできますが、それ以上は解放できません。

于 2013-03-01T06:53:50.770 に答える
0

の実装でmallocは、正確に1バイトが得られる可能性はほとんどありません。最も近い単語サイズにサイズ変更される可能性があります。これは、sizeof(int)そのスペースに収まるものであることを意味します。よく似ています:

struct foo {
    char a;
};

sizeof(struct foo)おそらく単語サイズになります。言うまでもなく、malloc(sizeof(int))を読みたいので、より多くのスペース(たとえば)を割り当てる必要がありintます。それが機能するように「起こる」という事実にもかかわらず、それは後のソフトウェア保守のためにそれほど混乱しないでしょう。未定義の動作である可能性があります。

于 2013-03-01T05:47:14.527 に答える
0

ニーズに十分なメモリを割り当てるのはあなたの責任です。コンパイラは、割り当てられた範囲外のメモリにアクセスしているかどうかをチェックしません。

xのメモリを割り当てて、xより大きいサイズの値を保存すると、実行時にアプリがクラッシュする場合があります(そうでない場合もあります)。それは未定義の振る舞いです。

を呼び出す場合malloc(1)、mallocは1つの引数(メモリのサイズ)を必要とし、それを渡すので、コンパイラが文句を言う必要はありません。

しかし、を呼び出すmalloc()と、ケースが異なり、コンパイラが文句を言います。

于 2013-03-01T05:46:07.803 に答える
0

未定義の動作?? malloc(1)空きブロックまたはサイズ 1 バイトを返します。返されたブロック以外にも、整数が書き込まれるブロックが存在する可能性があります (韻を踏んでいます!)。

明らかに、malloc()1 つの引数が必要です。何も指定しない場合、gcc文句を言い、C の標準に従う他のすべてのコンパイラも文句を言います。

sizeof(int)バイトが必要な場合:malloc(sizeof(int))

于 2013-03-01T05:43:46.543 に答える