Saya diberitahu bahwa kode berikut memiliki perilaku tidak terdefinisi hingga C ++ 20:
int *p = (int*)malloc(sizeof(int));
*p = 10;
Benarkah itu?
Argumennya adalah bahwa masa pakai int
objek tidak dimulai sebelum menetapkan nilainya ( P0593R6 ). Untuk mengatasi masalah tersebut, penempatan new
harus digunakan:
int *p = (int*)malloc(sizeof(int));
new (p) int;
*p = 10;
Apakah kita benar-benar harus memanggil konstruktor default yang sepele untuk memulai masa pakai objek?
Pada saat yang sama, kode tersebut tidak memiliki perilaku tidak terdefinisi dalam C murni. Tetapi, bagaimana jika saya mengalokasikan int
dalam kode C dan menggunakannya dalam kode C ++?
// C source code:
int *alloc_int(void)
{
int *p = (int*)malloc(sizeof(int));
*p = 10;
return p;
}
// C++ source code:
extern "C" int *alloc_int(void);
auto p = alloc_int();
*p = 20;
Apakah ini masih perilaku yang tidak terdefinisi?
c++
malloc
undefined-behavior
c++20
anton_rh
sumber
sumber
int
? Tidak. Untukstd::string
? Iya.int
, juga ya. Hanya saja dalam prakteknya tidak akan menimbulkan masalah jika tidak dilakukan. Sebabstd::string
, hal itu jelas akan menimbulkan masalah.int *p = (int*)malloc(sizeof(int)); p = new(p) int;
? Saya pernah menyadari bahwa tidak menetapkan hasil penempatan baru juga dapat menyebabkan efek yang fatal (meskipun mungkin terlihat agak konyol).Jawaban:
Iya. Secara teknis, tidak ada bagian dari:
int *p = (int*)malloc(sizeof(int));
sebenarnya membuat sebuah objek bertipe
int
, jadi dereferencingp
adalah UB karena tidak ada aktualnya diint
sana.Apakah Anda harus sesuai dengan model objek C ++ untuk menghindari perilaku tidak terdefinisi sebelum C ++ 20? Iya. Apakah ada kompiler yang benar-benar membahayakan jika Anda tidak melakukan ini? Aku tidak menyadarinya.
Iya. Sebelum C ++ 20, Anda masih belum benar-benar membuat
int
objek di mana pun jadi ini adalah UB.sumber
int
contoh - masa pakaiint
objek dimulai di sana.Ya, UB. Daftar cara sebuah
int
bisa ada disebutkan, dan tidak ada yang berlaku di sana, kecuali Anda berpendapat bahwa malloc itu acausal.Ini secara luas dianggap sebagai kekurangan dalam standar, tetapi salah satu yang kurang penting, karena optimasi yang dilakukan oleh kompiler C ++ di sekitar bit tertentu UB tidak menimbulkan masalah dengan use case tersebut.
Adapun pertanyaan ke-2, C ++ tidak mengamanatkan bagaimana C ++ dan C berinteraksi. Jadi semua interaksi dengan C adalah ... UB, alias perilaku tidak ditentukan oleh standar C ++.
sumber
extern "C"
sintaks sama sekali.gcc -fno-strict-aliasing
, atau MSVC secara default). Mengatakan "implementasi yang ditentukan" akan membutuhkan semua implementasi C ++ untuk menentukan beberapa cara di mana mereka beroperasi dengan beberapa implementasi C, jadi masuk akal untuk menyerahkan sepenuhnya pada implementasi apakah mereka ingin melakukan hal seperti itu atau tidak.