Yang lain sudah menjawab bagaimana malloc(0)
bekerja. Saya akan menjawab salah satu pertanyaan yang Anda ajukan yang belum terjawab (menurut saya). Pertanyaannya adalah tentang realloc(malloc(0), 0)
:
Apa artinya
malloc(0)
kembali? Apakah jawabannya sama untukrealloc(malloc(0),0)
?
Standar mengatakan ini tentang realloc(ptr, size)
:
- jika
ptr
adalahNULL
, berperilaku sepertimalloc(size)
, - jika tidak (
ptr
bukanNULL
), ini membatalkan alokasi penunjuk objek lama menjadiptr
dan mengembalikan pointer ke buffer yang dialokasikan baru. Tetapi jikasize
adalah 0, C89 mengatakan bahwa efeknya setara denganfree(ptr)
. Menariknya, saya tidak dapat menemukan pernyataan itu di draf C99 (n1256 atau n1336). Di C89, satu-satunya nilai yang masuk akal untuk dikembalikan dalam kasus itu adalahNULL
.
Jadi, ada dua kasus:
malloc(0)
mengembalikanNULL
pada sebuah implementasi. Lalurealloc()
Anda panggilan setara denganrealloc(NULL, 0)
. Itu setara denganmalloc(0)
dari atas (yaituNULL
dalam hal ini).malloc(0)
mengembalikan non-NULL
. Kemudian, panggilan tersebut setara denganfree(malloc(0))
. Dalam hal ini,malloc(0)
danrealloc(malloc(0), 0)
adalah tidak setara.
Perhatikan bahwa ada kasus yang menarik di sini:dalam kasus kedua, ketika malloc(0)
mengembalikan non-NULL
jika berhasil, mungkin masih mengembalikan NULL
untuk menunjukkan kegagalan. Ini akan menghasilkan panggilan seperti:realloc(NULL, 0)
, yang setara dengan malloc(0)
, yang mungkin mengembalikan NULL
atau tidak .
Saya tidak yakin apakah kelalaian dalam C99 merupakan kekeliruan atau apakah itu berarti bahwa dalam C99, realloc(ptr, 0)
untuk non-NULL
ptr
tidak setara dengan free(ptr)
. Saya baru saja mencobanya dengan gcc -std=c99
, dan di atas setara dengan free(ptr)
.
Edit :Saya pikir saya mengerti apa kebingungan Anda:
Mari kita lihat cuplikan dari kode contoh Anda:
ptr = malloc(0);
if (ptr == realloc(ptr, 1024))
Di atas tidak sama dengan malloc(0) == realloc(malloc(0), 1024)
. Yang kedua, malloc()
panggilan dilakukan dua kali, sedangkan yang pertama, Anda meneruskan penunjuk yang dialokasikan sebelumnya ke realloc()
.
Mari kita analisis kode pertama terlebih dahulu. Dengan asumsi malloc(0)
tidak mengembalikan NULL
jika berhasil, ptr
memiliki nilai yang valid. Ketika Anda melakukan realloc(ptr, 1024)
, realloc()
pada dasarnya memberi Anda buffer baru yang berukuran 1024, dan ptr
menjadi tidak valid. Implementasi yang sesuai dapat mengembalikan alamat yang sama dengan yang sudah ada di ptr
. Jadi, if
Anda kondisi dapat kembali benar. (Perhatikan, bagaimanapun, melihat nilai ptr
setelah realloc(ptr, 1024)
mungkin perilaku yang tidak ditentukan.)
Sekarang pertanyaan yang Anda ajukan:malloc(0) == realloc(malloc(0), 1024)
. Dalam hal ini, mari kita asumsikan bahwa malloc(0)
di LHS dan RHS mengembalikan non-NULL
. Kemudian, mereka dijamin berbeda. Juga, nilai kembalian dari malloc()
di LHS belum free()
belum, jadi malloc()
lainnya , calloc()
, atau realloc()
mungkin tidak mengembalikan nilai tersebut. Ini berarti bahwa jika Anda menulis kondisi Anda sebagai:
if (malloc(0) == realloc(malloc(0), 1024)
puts("possible");
Anda tidak akan melihat possible
pada keluaran (kecuali keduanya malloc()
dan realloc()
gagal dan kembalikan NULL
).
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
void *p1;
void *p2;
p1 = malloc(0);
p2 = realloc(p1, 1024);
if (p1 == p2)
puts("possible, OK");
/* Ignore the memory leaks */
if (malloc(0) == realloc(malloc(0), 1024))
puts("shouldn't happen, something is wrong");
return 0;
}
Di OS X, kode saya tidak menampilkan apa pun saat saya menjalankannya. Di Linux, ia mencetak possible, OK
.
malloc(0)
adalah Implementasi Ditetapkan sejauh menyangkut C99.
Dari C99 [Bagian 7.20.3]
Urutan dan kedekatan penyimpanan yang dialokasikan oleh panggilan berturut-turut ke fungsi calloc, malloc, dan realloc tidak ditentukan . Pointer dikembalikan jika alokasiberhasil disejajarkan sehingga dapat ditugaskan ke pointer ke semua jenis objek dan kemudian digunakan untuk mengakses objek tersebut atau larik objek tersebut di ruang yang dialokasikan (sampai ruang tersebut secara eksplisit didealokasi). Masa pakai objek yang dialokasikan meluas dari alokasi hingga deallokasi. Setiap alokasi tersebut akan menghasilkan penunjuk ke objek yang terpisah dari objek lainnya. Pointer mengembalikan poin ke awal (alamat byte terendah) dari ruang yang dialokasikan. Jika ruang tidak dapat dialokasikan, penunjuk nol dikembalikan. Jika ukuran ruang yang diminta adalah nol, perilaku ditentukan oleh implementasi :apakah pointer nol dikembalikan, atau perilaku seolah-olah ukurannya adalah nilai bukan nol, kecuali bahwa pointer yang dikembalikan tidak boleh digunakan untuk mengakses objek.
Di C89, malloc(0) bergantung pada implementasi - saya tidak tahu apakah C99 telah memperbaikinya atau tidak. Di C++, gunakan:
char * p = new char[0];
terdefinisi dengan baik - Anda mendapatkan penunjuk yang valid dan bukan nol. Tentu saja, Anda tidak dapat menggunakan penunjuk untuk mengakses apa yang ditunjuk tanpa menerapkan perilaku yang tidak ditentukan.
Mengenai mengapa hal ini ada, akan lebih mudah untuk beberapa algoritme, dan berarti Anda tidak perlu mengotori kode Anda dengan pengujian untuk nilai nol.