Apa perbedaan antara melakukan:
ptr = (char **) malloc (MAXELEMS * sizeof(char *));
atau:
ptr = (char **) calloc (MAXELEMS, sizeof(char*));
Kapan sebaiknya menggunakan calloc over malloc atau sebaliknya?
ptr = calloc(MAXELEMS, sizeof(*ptr));
Apa perbedaan antara melakukan:
ptr = (char **) malloc (MAXELEMS * sizeof(char *));
atau:
ptr = (char **) calloc (MAXELEMS, sizeof(char*));
Kapan sebaiknya menggunakan calloc over malloc atau sebaliknya?
ptr = calloc(MAXELEMS, sizeof(*ptr));
Jawaban:
calloc()memberi Anda buffer nol diinisialisasi, sementara malloc()meninggalkan memori tidak diinisialisasi.
Untuk alokasi besar, sebagian besar callocimplementasi di bawah OS mainstream akan mendapatkan halaman-halaman yang diketahui dari OS (misalnya melalui POSIX mmap(MAP_ANONYMOUS)atau Windows VirtualAlloc) sehingga tidak perlu menuliskannya di ruang pengguna. Ini adalah cara normal mallocmendapatkan lebih banyak halaman dari OS juga; callochanya memanfaatkan jaminan OS.
Ini berarti callocmemori masih bisa "bersih" dan dialokasikan dengan malas, dan copy-on-write dipetakan ke halaman fisik nol bersama sistem. (Dengan asumsi sistem dengan memori virtual.)
Beberapa kompiler bahkan dapat mengoptimalkan malloc + memset (0) menjadi calloc untuk Anda, tetapi Anda harus menggunakan calloc secara eksplisit jika Anda ingin memori dibaca sebagai 0.
Jika Anda tidak akan pernah membaca memori sebelum menulisnya, gunakan mallocsehingga dapat (berpotensi) memberi Anda memori kotor dari daftar bebas internalnya alih-alih mendapatkan halaman baru dari OS. (Atau alih-alih mem-blok memori pada daftar gratis untuk alokasi kecil).
Implementasi tertanam dari callocmungkin membiarkannya callocsendiri ke memori nol jika tidak ada OS, atau itu bukan OS multi-pengguna yang mewah yang nol halaman untuk menghentikan kebocoran informasi antara proses.
Pada embedded Linux, malloc bisa mmap(MAP_UNINITIALIZED|MAP_ANONYMOUS), yang hanya diaktifkan untuk beberapa kernel tertanam karena tidak aman pada sistem multi-pengguna.
callocbelum tentu lebih mahal, karena OS dapat melakukan beberapa trik untuk mempercepatnya. Saya tahu bahwa FreeBSD, ketika mendapat waktu CPU yang tidak digunakan, menggunakannya untuk menjalankan proses sederhana yang hanya berputar dan mengeluarkan blok memori yang tidak dapat dialokasikan, dan menandai blok dengan demikian memproses dengan sebuah flag. Jadi ketika Anda melakukannya calloc, itu pertama-tama mencoba untuk menemukan salah satu dari blok pre-zeroed tersebut dan hanya memberikannya kepada Anda - dan kemungkinan besar itu akan menemukannya.
Perbedaan yang kurang diketahui adalah bahwa dalam sistem operasi dengan alokasi memori optimis, seperti Linux, penunjuk yang dikembalikan malloctidak didukung oleh memori nyata hingga program benar-benar menyentuhnya.
callocmemang menyentuh memori (itu menulis nol di atasnya) dan dengan demikian Anda akan yakin OS mendukung alokasi dengan RAM aktual (atau swap). Ini juga mengapa lebih lambat dari malloc (tidak hanya harus nol itu, OS juga harus menemukan area memori yang sesuai dengan mungkin menukar proses lain)
Lihat misalnya pertanyaan SO ini untuk diskusi lebih lanjut tentang perilaku malloc
calloctidak perlu menulis nol. Jika blok yang dialokasikan sebagian besar terdiri dari nol halaman baru yang disediakan oleh sistem operasi, itu dapat membuat mereka tidak tersentuh. Ini tentu saja perlu callocdisetel ke sistem operasi daripada fungsi perpustakaan umum di atas malloc. Atau, implementor dapat callocmembandingkan setiap kata dengan nol sebelum mem-nolkannya. Ini tidak akan menghemat waktu, tetapi itu akan menghindari mengotori halaman baru.
dlmallocImplementasi all- like melewatkan memsetjika chunk diperoleh melalui mmaping anonim baru (atau setara). Biasanya jenis alokasi ini digunakan untuk potongan yang lebih besar, mulai dari 256k atau lebih. Saya tidak tahu ada implementasi yang melakukan perbandingan terhadap nol sebelum menulis nol selain dari saya sendiri.
omallocjuga melewatkan memset; calloctidak perlu menyentuh halaman apa pun yang belum pernah digunakan oleh aplikasi (cache halaman), selamanya. Padahal, implementasi yang sangat primitifcalloc berbeda.
Salah satu keuntungan yang sering diabaikan callocadalah bahwa (implementasi konforman) itu akan membantu melindungi Anda terhadap kerentanan integer overflow. Membandingkan:
size_t count = get_int32(file);
struct foo *bar = malloc(count * sizeof *bar);
vs.
size_t count = get_int32(file);
struct foo *bar = calloc(count, sizeof *bar);
Yang pertama dapat menghasilkan alokasi kecil dan buffer overflow berikutnya, jika countlebih besar dari SIZE_MAX/sizeof *bar. Yang terakhir akan secara otomatis gagal dalam hal ini karena objek yang besar tidak dapat dibuat.
Tentu saja Anda mungkin harus mencari implementasi yang tidak sesuai yang mengabaikan kemungkinan overflow ... Jika ini merupakan masalah pada platform yang Anda targetkan, Anda harus melakukan tes manual untuk overflow.
charini tidak overflow melainkan konversi pelaksanaan yang ditetapkan ketika menetapkan hasil kembali menjadi charobjek.
size_t64-bit jadi itu tidak masalah", itu cara berpikir yang cacat yang akan mengarah pada bug keamanan. size_tadalah tipe abstrak yang mewakili ukuran, dan tidak ada alasan untuk berpikir produk arbitrer dari nomor 32-bit dan size_t(catatan: sizeof *barpada prinsipnya bisa lebih besar dari 2 ^ 32 pada implementasi C 64-bit!) cocok size_t.
Dokumentasi membuat calloc terlihat seperti malloc, yang hanya menginisialisasi-nol memori; ini bukan perbedaan utama! Gagasan calloc adalah abstact semantik copy-on-write untuk alokasi memori. Ketika Anda mengalokasikan memori dengan calloc itu semua peta ke halaman fisik yang sama yang diinisialisasi ke nol. Ketika salah satu halaman dari memori yang dialokasikan ditulis ke dalam halaman fisik dialokasikan. Ini sering digunakan untuk membuat tabel hash BESAR, misalnya karena bagian hash yang kosong tidak didukung oleh memori tambahan (halaman); mereka dengan senang hati menunjuk ke halaman tanpa inisialisasi tunggal, yang bahkan dapat dibagikan di antara proses.
Setiap penulisan ke alamat virtual dipetakan ke halaman, jika halaman itu adalah halaman nol, halaman fisik lain dialokasikan, halaman nol disalin di sana dan aliran kontrol dikembalikan ke proses klien. Ini berfungsi dengan cara yang sama memori memetakan file, memori virtual, dll bekerja .. menggunakan paging.
Berikut adalah satu cerita pengoptimalan tentang topik ini: http://blogs.fau.de/hager/2007/05/08/benchmarking-fun-with-calloc-and-zero-pages/
Tidak ada perbedaan dalam ukuran blok memori yang dialokasikan. callochanya mengisi blok memori dengan pola fisik semua-nol-bit. Dalam praktiknya sering diasumsikan bahwa objek yang terletak di blok memori yang dialokasikan dengan callocnilai initilial seolah-olah mereka diinisialisasi dengan literal 0, yaitu integer harus memiliki nilai 0, variabel floating-point - nilai 0.0, pointer - nilai null-pointer yang sesuai , dan seterusnya.
Dari sudut pandang pedantic, calloc(dan juga memset(..., 0, ...)) hanya dijamin untuk menginisialisasi objek (dengan nol) dengan benar unsigned char. Segala sesuatu yang lain tidak dijamin diinisialisasi dengan benar dan mungkin mengandung apa yang disebut representasi perangkap , yang menyebabkan perilaku tidak terdefinisi. Dengan kata lain, untuk semua tipe selain unsigned charpatterma semua-nol-bit yang disebutkan di atas mungkin mewakili nilai ilegal, representasi trap.
Kemudian, di salah satu Teknis Corrigenda ke standar C99, perilaku didefinisikan untuk semua tipe integer (yang masuk akal). Yaitu secara formal, dalam bahasa C saat ini Anda hanya dapat menginisialisasi tipe integer dengan calloc(dan memset(..., 0, ...)). Menggunakannya untuk menginisialisasi hal lain dalam kasus umum mengarah ke perilaku yang tidak terdefinisi, dari sudut pandang bahasa C.
Dalam praktiknya, callocberfungsi, seperti yang kita semua ketahui :), tetapi apakah Anda ingin menggunakannya (mengingat di atas) terserah Anda. Saya pribadi lebih suka menghindarinya sepenuhnya, gunakan mallocsaja dan lakukan inisialisasi saya sendiri.
Akhirnya, detail penting lainnya adalah yang callocdiperlukan untuk menghitung ukuran blok akhir secara internal , dengan mengalikan ukuran elemen dengan jumlah elemen. Saat melakukan itu, callocharus memperhatikan kemungkinan aritmatika meluap. Ini akan menghasilkan alokasi yang gagal (pointer nol) jika ukuran blok yang diminta tidak dapat dihitung dengan benar. Sementara itu, mallocversi Anda tidak berusaha untuk menonton meluap. Ini akan mengalokasikan sejumlah memori yang "tidak dapat diprediksi" jika terjadi overflow.
memset(p, v, n * sizeof type);masalah karena n * sizeof typemungkin meluap. Kira saya perlu menggunakan for(i=0;i<n;i++) p[i]=v;loop untuk kode yang kuat.
nelemen ada di mana elemen memiliki ukuran sizeof type, maka n*sizeof typetidak bisa meluap, karena ukuran maksimum objek apa pun harus kurang dari SIZE_MAX.
SIZE_MAX, namun tidak ada array di sini. Pointer yang dikembalikan dari calloc()kaleng menunjuk ke memori yang dialokasikan melebihi SIZE_MAX. Banyak implementasi yang membatasi produk dari 2 args to calloc()to SIZE_MAX, namun spesifikasi C tidak memaksakan batas itu.
dari artikel Benchmarking bersenang-senang dengan calloc () dan nol halaman di Blog Georg Hager
Saat mengalokasikan memori menggunakan calloc (), jumlah memori yang diminta tidak langsung dialokasikan. Sebaliknya, semua halaman yang termasuk dalam blok memori terhubung ke satu halaman yang berisi semua nol oleh beberapa sihir MMU (tautan di bawah). Jika halaman tersebut hanya dibaca (yang berlaku untuk array b, c dan d dalam versi asli dari tolok ukur), data disediakan dari halaman nol tunggal, yang - tentu saja - cocok dengan cache. Begitu banyak untuk kernel loop yang terikat memori. Jika sebuah halaman ditulis (tidak peduli bagaimana), kesalahan terjadi, halaman "nyata" dipetakan dan halaman nol disalin ke memori. Ini disebut copy-on-write, pendekatan optimasi yang terkenal (yang saya bahkan telah mengajar beberapa kali dalam kuliah C ++ saya). Setelah itu,
callocumumnya malloc+memsetke 0
Biasanya sedikit lebih baik untuk digunakan malloc+memsetsecara eksplisit, terutama ketika Anda melakukan sesuatu seperti:
ptr=malloc(sizeof(Item));
memset(ptr, 0, sizeof(Item));
Itu lebih baik karena sizeof(Item)diketahui oleh kompiler pada waktu kompilasi dan kompiler dalam kebanyakan kasus akan menggantinya dengan instruksi terbaik ke nol memori. Di sisi lain jika memsetterjadi calloc, ukuran parameter alokasi tidak dikompilasi dalam callockode dan memsetsering disebut, yang biasanya berisi kode untuk mengisi byte-by-byte hingga batas panjang, daripada siklus untuk mengisi memori dalam sizeof(long)potongan dan akhirnya byte-by-byte mengisi ruang yang tersisa. Bahkan jika pengalokasi cukup pintar untuk memanggil beberapa aligned_memsetitu masih akan menjadi loop umum.
Satu pengecualian penting adalah ketika Anda melakukan malloc / calloc dari memori yang sangat besar (beberapa power_of_two kilobyte) di mana alokasi kasus dapat dilakukan langsung dari kernel. Karena kernel OS biasanya akan mem-nol semua memori yang mereka berikan untuk alasan keamanan, calloc yang cukup pintar mungkin akan mengembalikannya tanpa menambahkan zeroing tambahan. Sekali lagi - jika Anda hanya mengalokasikan sesuatu yang Anda tahu kecil, Anda mungkin lebih baik dengan malloc + memset kinerja-bijaksana.
calloc()lebih lambat daripada malloc(): perkalian untuk ukuran. calloc()diperlukan untuk menggunakan perkalian generik (jika size_t64 bit bahkan 64 bit yang sangat mahal * 64 bit = 64 bit operasi) sedangkan malloc () akan sering memiliki konstanta waktu kompilasi.
struct foo { char a,b,c; };. callocselalu lebih baik daripada malloc+ memset, jika Anda akan menghapus seluruh mallocwilayah ed. callocmemiliki pemeriksaan yang cermat tetapi efisien untuk int overflow dalam elemen ukuran * juga.
Perbedaan 1:
malloc() biasanya mengalokasikan blok memori dan ini adalah segmen memori yang diinisialisasi.
calloc() mengalokasikan blok memori dan menginisialisasi semua blok memori ke 0.
Perbedaan 2:
Jika Anda mempertimbangkan malloc()sintaks, hanya diperlukan 1 argumen. Perhatikan contoh berikut di bawah ini:
data_type ptr = (cast_type *)malloc( sizeof(data_type)*no_of_blocks );
Mis: Jika Anda ingin mengalokasikan 10 blok memori untuk tipe int,
int *ptr = (int *) malloc(sizeof(int) * 10 );
Jika Anda mempertimbangkan calloc()sintaks, itu akan membutuhkan 2 argumen. Perhatikan contoh berikut di bawah ini:
data_type ptr = (cast_type *)calloc(no_of_blocks, (sizeof(data_type)));
Mis: jika Anda ingin mengalokasikan 10 blok memori untuk tipe int dan Inisialisasi semua itu ke NOL,
int *ptr = (int *) calloc(10, (sizeof(int)));
Kesamaan:
Keduanya malloc()dan calloc()akan mengembalikan void * secara default jika tidak diketik.!
Ada dua perbedaan.
Pertama, ada dalam jumlah argumen. malloc()membutuhkan satu argumen (memori diperlukan dalam byte), sementara calloc()membutuhkan dua argumen.
Kedua, malloc()tidak menginisialisasi memori yang dialokasikan, sementara calloc()menginisialisasi memori yang dialokasikan ke NOL.
calloc()mengalokasikan area memori, panjangnya akan menjadi produk dari parameternya. callocmengisi memori dengan NOL dan mengembalikan pointer ke byte pertama. Jika gagal menemukan ruang yang cukup itu mengembalikan NULLpointer.Sintaks: ptr_var=(cast_type *)calloc(no_of_blocks , size_of_each_block);
yaituptr_var=(type *)calloc(n,s);
malloc()mengalokasikan satu blok memori dari REQUSTED SIZE dan mengembalikan pointer ke byte pertama. Jika gagal menemukan jumlah memori yang dibutuhkan, ia mengembalikan pointer nol.Sintaks: ptr_var=(cast_type *)malloc(Size_in_bytes);
The malloc()Fungsi mengambil satu argumen, yang merupakan jumlah byte untuk mengalokasikan, sedangkan calloc()fungsi membutuhkan dua argumen, salah satunya adalah jumlah elemen, dan yang lainnya adalah jumlah byte untuk mengalokasikan untuk masing-masing elemen tersebut. Juga, calloc()inisialisasi ruang yang dialokasikan menjadi nol, sementara malloc()tidak.
The calloc()fungsi yang dideklarasikan di <stdlib.h>header yang menawarkan beberapa keunggulan dibandingkan malloc()fungsi.
malloc()dan calloc()merupakan fungsi dari pustaka standar C yang memungkinkan alokasi memori dinamis, artinya keduanya memungkinkan alokasi memori selama runtime.
Prototipe mereka adalah sebagai berikut:
void *malloc( size_t n);
void *calloc( size_t n, size_t t)
Terutama ada dua perbedaan antara keduanya:
Perilaku: malloc()mengalokasikan blok memori, tanpa menginisialisasi, dan membaca konten dari blok ini akan menghasilkan nilai-nilai sampah. calloc(), di sisi lain, mengalokasikan blok memori dan menginisialisasi ke nol, dan jelas membaca konten blok ini akan menghasilkan nol.
Sintaks: malloc()mengambil 1 argumen (ukuran untuk dialokasikan), dan calloc()mengambil dua argumen (jumlah blok yang dialokasikan dan ukuran masing-masing blok).
Nilai kembali dari keduanya adalah pointer ke blok memori yang dialokasikan, jika berhasil. Jika tidak, NULL akan dikembalikan yang menunjukkan kegagalan alokasi memori.
Contoh:
int *arr;
// allocate memory for 10 integers with garbage values
arr = (int *)malloc(10 * sizeof(int));
// allocate memory for 10 integers and sets all of them to 0
arr = (int *)calloc(10, sizeof(int));
Fungsi yang sama seperti yang calloc()dapat dicapai menggunakan malloc()dan memset():
// allocate memory for 10 integers with garbage values
arr= (int *)malloc(10 * sizeof(int));
// set all of them to 0
memset(arr, 0, 10 * sizeof(int));
Catatan yang malloc()lebih disukai digunakan calloc()karena lebih cepat. Jika inisialisasi nol nilai diinginkan, gunakan calloc()sebagai gantinya.
Perbedaan yang belum disebutkan: batas ukuran
void *malloc(size_t size)hanya dapat mengalokasikan hingga SIZE_MAX.
void *calloc(size_t nmemb, size_t size);dapat mengalokasikan sekitar SIZE_MAX*SIZE_MAX.
Kemampuan ini tidak sering digunakan di banyak platform dengan pengalamatan linier. Sistem seperti membatasi calloc()dengan nmemb * size <= SIZE_MAX.
Pertimbangkan jenis 512 byte yang dipanggil disk_sectordan kode ingin menggunakan banyak sektor. Di sini, kode hanya dapat digunakan hingga SIZE_MAX/sizeof disk_sectorsektor.
size_t count = SIZE_MAX/sizeof disk_sector;
disk_sector *p = malloc(count * sizeof *p);
Pertimbangkan hal-hal berikut yang memungkinkan alokasi yang lebih besar.
size_t count = something_in_the_range(SIZE_MAX/sizeof disk_sector + 1, SIZE_MAX)
disk_sector *p = calloc(count, sizeof *p);
Sekarang jika sistem seperti itu dapat memasok alokasi yang begitu besar adalah masalah lain. Sebagian besar hari ini tidak akan. Namun itu telah terjadi selama bertahun-tahun ketika SIZE_MAX65535. Diberikan hukum Moore , menduga ini akan terjadi sekitar 2030 dengan model memori tertentu dengan SIZE_MAX == 4294967295dan kumpulan memori dalam 100 GBytes.
size_tlebih besar dari 32 bit. Satu-satunya pertanyaan adalah apakah menggunakan callocdengan nilai-nilai yang produknya melebihi SIZE_MAXdapat diandalkan untuk menghasilkan nol daripada mengembalikan pointer ke alokasi yang lebih kecil.
calloc()alokasi melebihi SIZE_MAX. Itu telah terjadi di masa lalu dengan 16-bit size_tdan karena memori terus memudar, saya tidak melihat alasan itu tidak akan terjadi bahkan jika itu tidak umum .
SIZE_MAX. Jelas tidak mensyaratkan bahwa ada keadaan di mana alokasi semacam itu mungkin berhasil; Saya tidak yakin ada manfaat khusus dari mandat bahwa implementasi yang tidak dapat menangani alokasi tersebut harus dikembalikan NULL(terutama mengingat bahwa beberapa implementasi memiliki mallocpointer kembali ke ruang yang belum berkomitmen dan mungkin tidak tersedia ketika kode benar-benar mencoba untuk menggunakan Itu).
size_tke uint64_t?
Jumlah blok:
malloc () menetapkan satu blok memori yang diminta,
calloc () menetapkan beberapa blok memori yang diminta
Inisialisasi:
malloc () - tidak menghapus dan menginisialisasi memori yang dialokasikan.
calloc () - menginisialisasi memori yang dialokasikan oleh nol.
Kecepatan:
malloc () cepat.
calloc () lebih lambat dari malloc ().
Argumen & Sintaks:
malloc () membutuhkan 1 argumen:
byte
calloc () membutuhkan 2 argumen:
panjangnya
void *malloc(size_t bytes);
void *calloc(size_t length, size_t bytes);
Cara Alokasi memori:
Fungsi malloc memberikan memori 'ukuran' yang diinginkan dari tumpukan yang tersedia.
Fungsi calloc memberikan memori yang berukuran sama dengan 'num * size'.
Arti nama:
Nama malloc berarti "alokasi memori".
Nama calloc berarti "alokasi yang berdekatan".
mallockeluarga