0
gcc 4.5.1 c89

このソースコードは、mallocとcallocをよりよく理解するために作成しました。

わかりましたが、いくつか質問があります。

dev = malloc(number * sizeof *devices);

このcallocと同じです。私は記憶をクリアすることについて心配していません。

dev = calloc(number, sizeof *devices);

これをwhileループで5回実行する場合と比較して、正確には何ですか。

dev = malloc(sizeof *devices);

最初のものと2番目のものは5構造体デバイスへのポインターを作成していると思います。そして3つ目は、構造体デバイスへの単一のポインターを作成することですか?

私のプログラムは、valgrind --leak-check=fullを使用してコンパイルおよび実行されたこの3つの異なるメソッドを示しています。

アドバイスをありがとうございます。

#include <stdio.h>
#include <stdlib.h>

struct Devices {
#define MAX_NAME_SIZE 80
    size_t id;
    char name[MAX_NAME_SIZE];
};

struct Devices* create_device(struct Devices *dev);
void destroy_device(struct Devices *dev);

int main(void)
{
    size_t num_devices = 5;
    size_t i = 0;
    struct Devices *device = NULL;
    struct Devices *dev_malloc = NULL;
    struct Devices *dev_calloc = NULL;

    for(i = 0; i < num_devices; i++) {
        device = create_device(device);
        /* Assign values */
        device->id = i + 1;
        sprintf(device->name, "Device%zu", device->id);
        /* Print values */
        printf("ID ----- [ %zu ]\n", device->id);
        printf("Name --- [ %s ]\n", device->name);
        /* Test free */
        destroy_device(device);
    }

    printf("\n");
    dev_malloc = malloc(num_devices * sizeof *dev_malloc);
    for(i = 0; i < num_devices; i++) {
        /* Assign values */
        dev_malloc->id = i + 1;
        sprintf(dev_malloc->name, "dev_malloc%zu", dev_malloc->id);
        /* Print values */
        printf("ID ----- [ %zu ]\n", dev_malloc->id);
        printf("Name --- [ %s ]\n", dev_malloc->name);
    }
    /* Test free */
    destroy_device(dev_malloc);

    printf("\n");
    dev_calloc = calloc(num_devices, sizeof *dev_calloc);
    for(i = 0; i < num_devices; i++) {
        /* Assign values */
        dev_calloc->id = i + 1;
        sprintf(dev_calloc->name, "dev_calloc%zu", dev_calloc->id);
        /* Print values */
        printf("ID ----- [ %zu ]\n", dev_calloc->id);
        printf("Name --- [ %s ]\n", dev_calloc->name);
    }
    /* Test free */
    destroy_device(dev_calloc);

    return 0;
}

struct Devices* create_device(struct Devices *dev)
{
    /* Not checking for memory error - just simple test */
    return dev = malloc(sizeof *dev);
}

void destroy_device(struct Devices *dev)
{
    if(dev != NULL) {
        free(dev);
    }
}
4

7 に答える 7

5

calloc(a,b)とは、算術オーバーフローや型の問題の可能性、およびメモリがゼロバイトで満たされるmalloc(a*b)ことを保証するという事実を除いて、同等です。それぞれのサイズの要素callocの配列に使用できる割り当てられたメモリ(またはその逆)。一方、呼び出し時間により、サイズの個々のオブジェクトが個別に解放され、配列には含まれなくなります(ただし、それらのオブジェクトのアドレスはポインターの配列に格納できます)。abmalloc(b) aab

お役に立てれば。

于 2010-11-30T17:48:06.253 に答える
4

malloc(n)は、nバイトに加えてパディングとオーバーヘッドを割り当てます。

calloc(m、n)は、m * nバイトに加えてパディングとオーバーヘッドを割り当て、次にメモリをゼロにします。

それでおしまい。

于 2010-11-30T17:46:55.067 に答える
2

最初の2つは、連続したメモリに5つのデバイスのアレイを作成します。最後のmallocは5回実行され、連続したメモリにあることが保証されていない5つの個別のデバイスを作成します。

于 2010-11-30T17:44:45.583 に答える
2

わかりやすくするために編集

  • 最初のものと2番目のものは5構造体デバイスへのポインターを作成していると思います。そして3つ目は、構造体デバイスへの単一のポインターを作成することですか?

最初のものは、 smalloc(number * sizeof(*devices))を格納するのに十分なメモリを割り当てます。他の人が述べたように、このブロックをの配列のように扱うことができます。戻ってきたポインタは、ブロックの先頭を指します。numberDeviceDevice

int number = 5;
Device *ptr = malloc(number * sizeof(*ptr));
/* stuff */
free(ptr);

を使用する2番目のものcallocは同じことを行いますが、メモリを0に初期化します。ここでも、ブロックをの配列のように扱うことができますDevice

int number = 5;
Device *ptr = calloc(number, sizeof(*ptr));
/* stuff */
free(ptr);

3番目のループは5回ループし、それぞれ1つを格納するのに十分な大きさの5つの異なるブロックへの5つの異なるポインターになりDeviceます。これは、5つのポインタのそれぞれをfree個別に処理する必要があることも意味します。

Device *ptrs[5];
for(int i = 0; i < 5; ++i)
{
    ptrs[i] = malloc(sizeof(*ptrs[i]));
}
/* stuff */
for(int i = 0; i < 5; ++i)
{
    free(ptrs[i]);
}
于 2010-11-30T17:46:13.787 に答える
1

プログラムの3つのループはすべて、一度に1つのstruct Devicesオブジェクトのみを使用します。後者は、複数のオブジェクトを使用するかのように追加のメモリを割り当てますが、その後、そのメモリの先頭を上書きし続けます。ID 2のオブジェクトを設定した後、ID 1のオブジェクトを使用しようとすると、ID1のオブジェクトがなくなっていることがわかります。

代わりに、次のようにして、割り当てられたメモリを構造体の配列として扱うことができます。

dev_malloc = malloc(num_devices * sizeof *dev_malloc);
for (i=0; i<num_devices; i++) {
    /* Assign values */   
    dev_malloc[i].id = i + 1;   
    sprintf(dev_malloc[i].name, "dev_malloc%zu", dev_malloc[i].id);   
    /* Print values */   
    printf("ID ----- [ %zu ]\n", dev_malloc[i].id);   
    printf("Name --- [ %s ]\n", dev_malloc[i].name);
}
free(dev_malloc);
于 2010-11-30T17:55:29.530 に答える
1

callocの実装を見て、違いを確認してください。それはおそらく次のようなものです:

// SIZE_MAX is defined in stdint.h from C99
void *calloc( size_t N, size_t S)
{
    void *ret;
    size_t NBYTES;

    // check for overflow of size_t type
    if (N > SIZE_MAX / S) return NULL;

    NBYTES = N * S;
    ret = malloc( NBYTES);
    if (ret != NULL)
    {
        memset( ret, 0, NBYTES);
    }

    return ret;
}
于 2010-11-30T23:25:37.877 に答える
0

ご指摘callocのとおり、メモリは割り当てられますが、割り当てられmallocません。

例1と2は、それぞれ5つの構造体の単一の連続したブロックを割り当てます(そしてそのブロックへのポインターを返します)が、例3はそれぞれ1つの構造体の5つの別々のブロックを割り当てます(そして互いに無関係な5つのポインターを与えます)。

于 2010-11-30T17:44:02.943 に答える