กำลังใช้ malloc สำหรับพฤติกรรมที่ไม่ได้กำหนดไว้จนถึง C ++ 20


96

ฉันได้รับแจ้งว่ารหัสต่อไปนี้มีพฤติกรรมที่ไม่ได้กำหนดไว้จนถึง C ++ 20:

int *p = (int*)malloc(sizeof(int));
*p = 10;

เป็นเช่นนั้นจริงหรือ?

อาร์กิวเมนต์คืออายุการใช้งานของintอ็อบเจ็กต์ไม่ได้เริ่มต้นก่อนกำหนดค่าให้กับมัน ( P0593R6 ) ในการแก้ไขปัญหาnewควรใช้ตำแหน่ง:

int *p = (int*)malloc(sizeof(int));
new (p) int;
*p = 10;

เราต้องเรียกตัวสร้างเริ่มต้นที่ไม่สำคัญเพื่อเริ่มอายุการใช้งานของวัตถุหรือไม่?

ในเวลาเดียวกันรหัสไม่มีพฤติกรรมที่ไม่ได้กำหนดใน C บริสุทธิ์ แต่จะเป็นอย่างไรถ้าฉันจัดสรรintรหัสใน C และใช้ในรหัส 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;

ยังไม่ได้กำหนดพฤติกรรมหรือไม่?


8
เพื่อint? ไม่สำหรับstd::string? ใช่.
Eljay

8
@ เอลเจย์ฟอintร์ก็เช่นกัน เพียงแค่ว่ามันจะไม่ก่อให้เกิดปัญหาในทางปฏิบัติหากคุณไม่ทำ เพราะstd::stringมันจะทำให้เกิดปัญหาอย่างเห็นได้ชัด
Barry

ก่อน C ++ 20 คุณสามารถเพิ่มตำแหน่งใหม่ได้ จากนั้นจะก่อตัวขึ้นอย่างดีและอาจไม่มีค่าใช้จ่ายใด ๆ
François Andrieux

8
กฎใหม่ใน C ++ 20 ที่เปลี่ยนแปลงสิ่งนี้คืออะไร?
Kevin

4
ควรint *p = (int*)malloc(sizeof(int)); p = new(p) int;หรือไม่? ฉันเคยตระหนักว่าการไม่กำหนดผลลัพธ์ของการจัดวางใหม่อาจทำให้เกิดผลเสียเช่นกัน (แม้ว่ามันอาจจะดูงี่เง่าไปหน่อยก็ตาม)
Scheff

คำตอบ:


62

มันจริงหรอ?

ใช่. ในทางเทคนิคไม่มีส่วนของ:

int *p = (int*)malloc(sizeof(int));

จริงสร้างวัตถุของการพิมพ์intดังนั้น dereferencing pเป็น UB เนื่องจากไม่มีจริงintมี

เราต้องเรียกตัวสร้างเริ่มต้นที่ไม่สำคัญเพื่อเริ่มอายุการใช้งานของวัตถุหรือไม่?

คุณต้องทำตามโมเดลอ็อบเจ็กต์ C ++ เพื่อหลีกเลี่ยงพฤติกรรมที่ไม่ได้กำหนดไว้ก่อน C ++ 20 หรือไม่? ใช่. คอมไพเลอร์ใด ๆ จะก่อให้เกิดอันตรายหากคุณไม่ทำเช่นนี้หรือไม่? ไม่ใช่ว่าฉันรู้

[... ] มันยังไม่ได้กำหนดพฤติกรรม?

ใช่. Pre-C ++ 20 คุณยังไม่ได้สร้างintออบเจ็กต์ที่ใดก็ได้ดังนั้นนี่คือ UB


ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเพิ่มเติม การสนทนานี้ได้รับการย้ายไปแชท
มักเย็น

เหตุใดภาษาในtimsong-cpp.github.io/cppwp/n3337/basic.life#1.1จึงไม่เพียงพอที่จะไม่เป็น UB intท้ายที่สุดแล้วการจัดเก็บขนาดและการจัดตำแหน่งที่เหมาะสมได้รับในตัวอย่าง - อายุการใช้งานของintวัตถุเริ่มต้นที่นั่น
avakar

41

ใช่มันคือ UB รายการวิธีที่intสามารถมีอยู่ได้ถูกแจกแจงและไม่มีใครใช้ที่นั่นเว้นแต่คุณจะถือว่า malloc นั้นเป็น acausal

ถือว่าเป็นข้อบกพร่องในมาตรฐานอย่างกว้างขวาง แต่มีความสำคัญต่ำเนื่องจากการเพิ่มประสิทธิภาพที่ทำโดยคอมไพเลอร์ C ++ รอบ ๆ บิตของ UB นั้นไม่ก่อให้เกิดปัญหากับกรณีการใช้งานนั้น

สำหรับคำถามที่ 2 C ++ ไม่ได้กำหนดว่า C ++ และ C โต้ตอบอย่างไร ดังนั้นการโต้ตอบทั้งหมดกับ C คือ ... UB หรือที่เรียกว่าพฤติกรรมที่ไม่ได้กำหนดโดยมาตรฐาน C ++


5
คุณสามารถขยายรายการวิธีที่แจกแจงเพื่อให้ int มีอยู่ได้หรือไม่? ฉันจำได้ว่าเคยถามคำถามที่คล้ายกันเกี่ยวกับอายุการใช้งานของสัตว์ประเภทดึกดำบรรพ์และมีคนบอกว่าดึกดำบรรพ์สามารถ "มีอยู่จริง" ได้เพียงแค่บอกว่ามันมีอยู่จริง ดูเหมือนว่าฉันอาจพลาดส่วนที่เป็นประโยชน์ของข้อมูลจำเพาะ! ฉันอยากรู้ว่าส่วนไหนที่ฉันควรอ่าน!
Cort Ammon

7
@CortAmmon รายการวิธีที่แจกแจงสำหรับอ็อบเจ็กต์ (ประเภทใดก็ได้) ที่มีอยู่ใน C ++ 20 อยู่ใน[intro.object] : (1) ตามคำจำกัดความ (2) โดยนิพจน์ใหม่ (3) โดยปริยายตามกฎใหม่ ใน P0593 (4) การเปลี่ยนสมาชิกที่ใช้งานอยู่ของสหภาพ (5) ชั่วคราว (3) เป็นสิ่งใหม่ใน C ++ 20, (4) เป็นสิ่งใหม่ใน C ++ 17
Barry

3
ปฏิสัมพันธ์ C / C ++ เป็น UB จริงหรือ? มันจะสมเหตุสมผลกว่าที่จะกำหนดการนำไปใช้งานแทนที่จะไม่ได้กำหนดไว้มิฉะนั้นจะแปลกที่จะมีextern "C"ไวยากรณ์เลย
Ruslan

4
@Ruslan: การใช้งานมีอิสระที่จะกำหนดพฤติกรรมใด ๆ ที่ ISO C ++ ไม่ได้กำหนดไว้ (ตัวอย่างเช่นgcc -fno-strict-aliasingหรือ MSVC โดยค่าเริ่มต้น) การกล่าวว่า "การใช้งานที่กำหนดไว้" จะต้องใช้การใช้งาน C ++ ทั้งหมดเพื่อกำหนดวิธีการที่จะทำงานร่วมกับการใช้งาน C บางอย่างดังนั้นจึงควรปล่อยให้มีการใช้งานอย่างเต็มที่ว่าพวกเขาต้องการทำอะไรเช่นนั้นหรือไม่
Peter Cordes

4
@PeterCordes: ฉันสงสัยว่าทำไมคนจำนวนมากถึงไม่รับรู้ถึงความแตกต่างระหว่าง IDB และ UB และใช้ความคิดที่เพ้อฝันว่าความล้มเหลวของ Standard ในการกำหนดให้การใช้งานทั้งหมดดำเนินการตามโครงสร้างอย่างมีความหมายซึ่งบ่งบอกถึงการตัดสินว่าไม่ควรคาดหวังให้มีการใช้งานเกิดขึ้น และการนำไปใช้งานที่ไม่ทำเช่นนั้นจะต้องไม่ถูกมองว่าด้อยกว่า
supercat
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.