Jawaban:
Menurut spesifikasinya, malloc (0) akan mengembalikan "pointer nol atau pointer unik yang berhasil diteruskan ke free ()".
Ini pada dasarnya memungkinkan Anda tidak mengalokasikan apa pun, tetapi tetap meneruskan variabel "artist" ke panggilan ke free () tanpa khawatir. Untuk tujuan praktis, ini hampir sama dengan melakukan:
artist = NULL;
Standar C (C17 7.22.3 / 1) mengatakan:
Jika ukuran ruang yang diminta adalah nol, perilaku implementasi didefinisikan: baik pointer nol dikembalikan, atau perilaku seolah-olah ukurannya adalah beberapa nilai bukan nol, kecuali bahwa pointer yang dikembalikan tidak boleh digunakan untuk mengakses objek.
Jadi, malloc(0)
bisa kembali NULL
atau penunjuk yang valid yang mungkin tidak dereferensi . Dalam kedua kasus, itu sangat valid untuk memanggilnya free()
.
Menurut saya tidak malloc(0)
banyak gunanya, kecuali dalam kasus ketika malloc(n)
dipanggil dalam loop misalnya, dan n
mungkin nol.
Melihat kode di tautan, saya yakin bahwa penulis memiliki dua kesalahpahaman:
malloc(0)
mengembalikan pointer yang valid selalu , danfree(0)
buruk.Jadi, dia memastikan bahwa artist
dan variabel lain selalu memiliki nilai "valid" di dalamnya. Komentar mengatakan sebanyak: // these must always point at malloc'd data
.
malloc(0)
mengembalikan pointer yang valid, malloc()
mengembalikan NULL
berarti selalu "gagal", dan 0
bukan kasus khusus lagi, yang lebih konsisten.
malloc
kegagalan untuk mendapatkan memori ditentukan oleh implementasi, implementasi dapat dengan mudah mendefinisikan bahwa alokasi size-0 selalu unsatisfiable ( ENOMEM
), dan sekarang malloc(0)
mengembalikan 0 (dengan errno==ENOMEM
) secara konsisten. :-)
realloc
mendapatkan pointer malloc(0)
? Bisa Anda realloc((char*)NULL)
?
malloc (0) adalah implementasi spesifik. Pustaka dapat mengembalikan NULL atau memiliki perilaku malloc biasa, tanpa alokasi memori. Apapun fungsinya, itu harus didokumentasikan di suatu tempat.
Biasanya, ini mengembalikan pointer yang valid dan unik tetapi TIDAK boleh dereferensi. Juga perhatikan bahwa itu BISA mengkonsumsi memori meskipun sebenarnya tidak mengalokasikan apa pun.
Dimungkinkan untuk mengalokasikan kembali pointer malloc (0) yang bukan null.
Memiliki malloc (0) verbatim tidak banyak gunanya. Ini sebagian besar digunakan ketika alokasi dinamis adalah nol byte dan Anda tidak peduli untuk memvalidasinya.
malloc()
harus menyimpan "informasi rumah tangga" di suatu tempat (ukuran blok yang dialokasikan misalnya, dan data tambahan lainnya). Jadi, jika malloc(0)
tidak dikembalikan NULL
, itu akan menggunakan memori untuk menyimpan informasi itu, dan jika tidak free()
d, akan menyebabkan kebocoran memori.
malloc()
akan ditampilkan oleh orang lain , atau dikembalikan NULL
.
malloc(0)
. Namun, dalam implementasi yang sama dari pustaka C standar, realloc(ptr, 0)
membebaskan ptr
dan mengembalikan NULL.
Ada jawaban di tempat lain di halaman ini yang dimulai dengan "malloc (0) akan mengembalikan alamat memori yang valid dan jangkauannya akan bergantung pada jenis penunjuk yang sedang dialokasikan memori". Pernyataan ini tidak benar (saya tidak memiliki reputasi yang cukup untuk mengomentari jawaban itu secara langsung, jadi tidak dapat meletakkan komentar ini langsung di bawah sana).
Melakukan malloc (0) tidak akan secara otomatis mengalokasikan memori dengan ukuran yang benar. Fungsi malloc tidak mengetahui apa yang Anda transmisikan hasilnya. Fungsi malloc hanya mengandalkan nomor ukuran yang Anda berikan sebagai argumennya. Anda perlu melakukan malloc (sizeof (int)) untuk mendapatkan penyimpanan yang cukup untuk menyimpan int, misalnya, bukan 0.
malloc(0)
tidak masuk akal bagi saya, kecuali kode tersebut mengandalkan perilaku khusus untuk implementasi. Jika kode dimaksudkan untuk menjadi portabel, maka itu harus memperhitungkan fakta bahwa pengembalian NULL dari malloc(0)
bukanlah kegagalan. Jadi mengapa tidak menetapkan NULL sajaartist
saja, karena itu adalah hasil sukses yang valid, dan lebih sedikit kode, dan tidak akan menyebabkan pemrogram pemeliharaan Anda meluangkan waktu untuk memahaminya?
malloc(SOME_CONSTANT_THAT_MIGHT_BE_ZERO)
atau malloc(some_variable_which_might_be_zero)
mungkin bisa memiliki kegunaannya, meskipun sekali lagi Anda harus lebih berhati-hati untuk tidak memperlakukan pengembalian NULL sebagai kegagalan jika nilainya 0, tetapi ukuran 0 seharusnya OK.
Ada banyak setengah jawaban benar di sekitar sini, jadi inilah fakta sebenarnya. Halaman manual untuk malloc()
mengatakan:
Jika ukurannya 0, maka malloc () mengembalikan NULL, atau nilai pointer unik yang nantinya bisa berhasil diteruskan ke free ().
Artinya, sama sekali tidak ada jaminan bahwa hasil dari malloc(0)
adalah unik atau tidak NULL. Satu-satunya jaminan disediakan oleh definisi free()
, sekali lagi, inilah yang dikatakan halaman manual:
Jika ptr adalah NULL, tidak ada operasi yang dilakukan.
Jadi, apa pun yang malloc(0)
dikembalikan, itu dapat diteruskan dengan aman free()
. Tapi begitu juga NULL
penunjuk.
Akibatnya, menulis artist = malloc(0);
tidak lebih baik daripada menulis artist = NULL;
malloc(0)
dapat menampilkan, katakanlah, 0x1, dan free()
dapat memiliki pemeriksaan kasus khusus 0x1 seperti halnya untuk 0x0.
NULL
, atau pointer unik". sebagai gantinya 'baik pointer nol atau pointer ke ruang yang dialokasikan ". Tidak ada persyaratan unik . OTOH, mengembalikan nilai khusus non-unik dapat mengganggu kode yang mengandalkan nilai unik. Mungkin pertanyaan kasus sudut untuk SO.
man
mungkin juga mendokumentasikan formulir yang ditentukan implementasi yang digunakan di * nix. Dalam hal ini tidak, tetapi masih bukan sumber kanonik untuk umum C.
Mengapa Anda tidak boleh melakukan ini ...
Karena nilai kembali malloc bergantung pada implementasi, Anda mungkin mendapatkan pointer NULL atau alamat lain kembali. Hal ini pada akhirnya dapat membuat heap-buffer overflows jika kode penanganan error tidak memeriksa ukuran dan nilai yang dikembalikan, yang menyebabkan masalah stabilitas (crash) atau bahkan masalah keamanan yang lebih buruk.
Pertimbangkan contoh ini, di mana mengakses memori lebih lanjut melalui alamat yang dikembalikan akan merusak ukuran heap iff adalah nol dan implementasi mengembalikan nilai non NULL kembali.
size_t size;
/* Initialize size, possibly by user-controlled input */
int *list = (int *)malloc(size);
if (list == NULL) {
/* Handle allocation error */
}
else {
/* Continue processing list */
}
Lihat halaman Secure Coding ini dari CERT Coding Standards tempat saya mengambil contoh di atas untuk bacaan lebih lanjut.
Memang, saya belum pernah melihat ini sebelumnya, ini adalah pertama kalinya saya melihat sintaks ini, bisa dibilang, kasus klasik fungsi berlebihan. Sehubungan dengan jawaban Reed, saya ingin menunjukkan bahwa ada hal serupa, yang tampak seperti fungsi yang kelebihan beban realloc
:
realloc(foo, size);
. Saat Anda meneruskan penunjuk non-NULL dan berukuran nol untuk realoc, realoc berperilaku seolah-olah Anda telah memanggil free (…)realloc(foo, size);
. Saat Anda meneruskan pointer NULL dan ukurannya bukan nol, realloc berperilaku seolah-olah Anda telah memanggil malloc (…)Semoga ini bisa membantu, Salam, Tom.
malloc (0) akan mengembalikan NULL atau pointer valid yang dapat diteruskan dengan benar ke free. Dan meskipun tampaknya memori yang ditunjukkannya tidak berguna atau tidak dapat ditulis atau dibaca, itu tidak selalu benar. :)
int *i = malloc(0);
*i = 100;
printf("%d", *i);
Kami mengharapkan kesalahan segmentasi di sini, tetapi yang mengejutkan, ini mencetak 100! Itu karena malloc sebenarnya meminta sebagian besar memori ketika kita memanggil malloc untuk pertama kalinya. Setiap panggilan ke malloc setelah itu, menggunakan memori dari potongan besar itu. Hanya setelah bagian besar itu selesai, ingatan baru diminta.
Penggunaan malloc (0): jika Anda berada dalam situasi di mana Anda ingin panggilan malloc berikutnya menjadi lebih cepat, memanggil malloc (0) harus melakukannya untuk Anda (kecuali untuk kasus edge).
*i
mungkin tidak macet dalam kasus Anda, tetapi itu perilaku yang tidak ditentukan. Waspadai setan hidung!
malloc(0)
yang tidak disebutkan. Pada implementasi yang mengembalikan nilai non-NULL, terutama dalam build DEBUG, kemungkinan akan mengalokasikan LEBIH BANYAK daripada yang Anda minta, dan memberi Anda penunjuk untuk melewati header internalnya. Ini memungkinkan Anda untuk merasakan penggunaan memori yang sebenarnya jika Anda mendapatkan ini sebelum dan sesudah serangkaian alokasi. misalnya: void* before = malloc(0); ... void* after = malloc(0); long long total = after - before;
atau semacamnya.
malloc(0)
. Bisakah Anda mengatakan bab mana yang Anda rujuk juga? Memberikan kutipan yang tepat juga akan menyenangkan.
Di Windows:
void *p = malloc(0);
akan mengalokasikan buffer panjang-nol pada heap lokal. Pointer yang dikembalikan adalah penunjuk heap yang valid.malloc
pada akhirnya memanggil HeapAlloc
menggunakan heap runtime C default yang kemudian memanggil RtlAllocateHeap
, dll.free(p);
digunakan HeapFree
untuk membebaskan buffer dengan panjang 0 di heap. Tidak membebaskannya akan mengakibatkan kebocoran memori.Ini sebenarnya cukup berguna, dan (jelas IMHO), perilaku yang diizinkan untuk mengembalikan pointer NULL rusak. Penunjuk dinamis berguna tidak hanya untuk apa yang ditunjukkannya, tetapi juga fakta bahwa alamatnya unik. Mengembalikan NULL menghapus properti kedua itu. Semua program mallocs I yang disematkan (sebenarnya cukup sering) memiliki perilaku ini.
Tidak yakin, menurut beberapa kode sumber malloc acak yang saya temukan, masukan 0 menghasilkan nilai kembali NULL. Jadi ini cara gila untuk menyetel pointer artis ke NULL.
http://www.raspberryginger.com/jbailey/minix/html/lib_2ansi_2malloc_8c-source.html
Berikut adalah analisis setelah menjalankan alat pemeriksaan memori valgrind.
==16740== Command: ./malloc0
==16740==
p1 = 0x5204040
==16740==
==16740== HEAP SUMMARY:
==16740== in use at exit: 0 bytes in 0 blocks
==16740== total heap usage: 2 allocs, 2 frees, 1,024 bytes allocated
==16740==
==16740== All heap blocks were freed -- no leaks are possible
dan inilah kode contoh saya:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
//int i;
char *p1;
p1 = (char *)malloc(0);
printf("p1 = %p\n", p1);
free(p1);
return 0;
}
Secara default 1024 byte dialokasikan. Jika saya meningkatkan ukuran malloc, byte yang dialokasikan akan meningkat 1025 dan seterusnya.
Menurut jawaban Reed Copsey dan halaman manual malloc, saya menulis beberapa contoh untuk diuji. Dan saya menemukan malloc (0) akan selalu memberikan nilai yang unik. Lihat contoh saya:
char *ptr;
if( (ptr = (char *) malloc(0)) == NULL )
puts("Got a null pointer");
else
puts("Got a valid pointer");
Outputnya adalah "Got a valid pointer", yang artinya ptr
tidak null.
malloc(0)
akan mengembalikan alamat memori yang valid dan jangkauannya akan bergantung pada jenis penunjuk yang dialokasikan memori. Anda juga dapat menetapkan nilai ke area memori tetapi ini harus dalam jangkauan dengan jenis penunjuk yang digunakan. Anda juga dapat mengosongkan memori yang dialokasikan. Saya akan menjelaskan ini dengan sebuah contoh:
int *p=NULL;
p=(int *)malloc(0);
free(p);
Kode di atas akan bekerja dengan baik di gcc
kompiler pada mesin Linux. Jika Anda memiliki kompiler 32 bit, maka Anda dapat memberikan nilai dalam kisaran integer, yaitu -2147483648 hingga 2147483647. Hal yang sama juga berlaku untuk karakter. Harap dicatat bahwa jika tipe pointer yang dideklarasikan berubah maka range nilai akan berubah terlepas dari malloc
typecast, mis
unsigned char *p=NULL;
p =(char *)malloc(0);
free(p);
p
akan mengambil nilai dari 0 sampai 255 dari char karena dideklarasikan sebagai unsigned int.
malloc()
tidak tahu apa-apa tentang pemeran (yang sebenarnya sepenuhnya berlebihan dalam C). Membedakan nilai kembalian malloc(0)
akan memicu perilaku yang tidak ditentukan.
Hanya untuk memperbaiki kesan yang salah di sini:
artist = (char *) malloc(0);
tidak akan pernah kembali NULL
; itu tidak sama dengan artist = NULL;
. Menulis sebuah program yang sederhana dan membandingkan artist
dengan NULL
. if (artist == NULL)
salah dan if (artist)
benar.