GNU/Linux >> Belajar Linux >  >> Linux

Apa yang dikembalikan malloc(0)?

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 untuk realloc(malloc(0),0) ?

Standar mengatakan ini tentang realloc(ptr, size) :

  • jika ptr adalah NULL , berperilaku seperti malloc(size) ,
  • jika tidak (ptr bukan NULL ), ini membatalkan alokasi penunjuk objek lama menjadi ptr dan mengembalikan pointer ke buffer yang dialokasikan baru. Tetapi jika size adalah 0, C89 mengatakan bahwa efeknya setara dengan free(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 adalah NULL .

Jadi, ada dua kasus:

  • malloc(0) mengembalikan NULL pada sebuah implementasi. Lalu realloc() Anda panggilan setara dengan realloc(NULL, 0) . Itu setara dengan malloc(0) dari atas (yaitu NULL dalam hal ini).
  • malloc(0) mengembalikan non-NULL . Kemudian, panggilan tersebut setara dengan free(malloc(0)) . Dalam hal ini, malloc(0) dan realloc(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.


Linux
  1. Apa Artinya “–” (tanda hubung ganda)?

  2. Apa yang Dilakukan "lc_all=c"?

  3. Apa?

  1. Apa itu Exec 3?

  2. Apa yang Bamfdaemon Lakukan?

  3. Apa yang dilakukan ulimit -s unlimited?

  1. Apa yang Digema $? Mengerjakan??

  2. Apa yang Sebenarnya Dilakukan Libgl_always_indirect=1?

  3. Apa yang dilakukan kill -- -0?