`string.assign (string.data (), 5)` มีการกำหนดชัดเจนหรือ UB หรือไม่


11

เพื่อนร่วมงานต้องการเขียนสิ่งนี้:

std::string_view strip_whitespace(std::string_view sv);

std::string line = "hello  ";
line = strip_whitespace(line);

ผมบอกว่ากลับมาstring_viewทำให้ฉันไม่สบายใจเบื้องต้นและนอกจาก aliasing ที่นี่ดูเหมือน UB ให้ฉัน

ฉันสามารถพูดด้วยความมั่นใจว่าในกรณีนี้จะเทียบเท่ากับline = strip_whitespace(line) line = std::string_view(line.data(), 5)ฉันเชื่อว่าจะเรียกstring::operator=(const T&) [with T=string_view]ซึ่งถูกกำหนดให้เทียบเท่ากับline.assign(const T&) [with T=string_view]ซึ่งถูกกำหนดให้เทียบเท่ากับline.assign(line.data(), 5)ซึ่งถูกกำหนดให้ทำเช่นนี้:

Preconditions: [s, s + n) is a valid range.
Effects: Replaces the string controlled by *this with a copy of the range [s, s + n).
Returns: *this.

แต่นี่ไม่ได้บอกว่าจะเกิดอะไรขึ้นเมื่อมีนามแฝง

ฉันถามคำถามนี้ใน cpplang Slack เมื่อวานและได้คำตอบที่หลากหลาย ค้นหาคำตอบที่มีสิทธิ์อย่างยิ่งที่นี่และ / หรือการวิเคราะห์เชิงประจักษ์เกี่ยวกับการใช้งานของผู้จำหน่ายห้องสมุดจริง


ผมเขียนกรณีทดสอบสำหรับstring::assign, vector::assign, deque::assign, และlist::assignforward_list::assign

  • Libc ++ ทำให้กรณีทดสอบเหล่านี้ใช้งานได้
  • Libstdc ++ ทำให้พวกเขาทำงานทั้งหมดยกเว้นforward_listsegfaults ใด
  • ฉันไม่รู้เกี่ยวกับห้องสมุดของ MSVC

segfault ใน libstdc ++ ให้ฉันหวังว่านี่คือ UB; แต่ฉันก็เห็นทั้ง libc ++ และ libstdc ++ ด้วยความพยายามอย่างมากในการทำให้งานนี้เป็นอย่างน้อยในกรณีทั่วไป


คุณได้รวบรวมกรณีทดสอบกับ ASan และ / หรือรันภายใต้ Valgrind หรือไม่? ที่จะนำการคาดเดาออกมาว่ารหัสก่อให้เกิดการละเมิดการเข้าถึงหรือไม่แม้ว่าจะยังคงใช้งานได้จริงมากกว่าที่จะเป็นคำจำกัดความ
Konrad Rudolph

1
"ถ้าฟังก์ชั่นสมาชิกหรือโอเปอเรเตอร์ของ basic_string มีข้อผิดพลาดฟังก์ชันหรือโอเปอเรเตอร์นั้นจะไม่มีผลกระทบใด ๆ กับออบเจ็กต์ basic_string" - *thisนี้จัดสรรกองกำลังของการจัดเก็บที่เกิดขึ้นก่อนการจัดเก็บข้อมูลที่มีอยู่ได้รับอิสระเพื่อให้มีข้อยกเว้นได้รับโยนถ้าจัดสรรล้มเหลวโดยไม่ต้องเปลี่ยน แต่ฉันไม่เห็นอะไรเลยที่จะป้องกันการจัดเก็บที่มีอยู่ถูกนำมาใช้ซ้ำซึ่งในกรณีนี้จะไม่ได้ระบุเนื่องจากความหมายของการคัดลอกการเก็บข้อมูลเกินความเป็นจริง
Sam Varshavchik


2
สำหรับบรรจุลำดับที่กล่าวถึงเป็นที่แน่นอน UB เพราะการละเมิดเงื่อนไขของassignความต้องการในแท็บ [: container.seq.req]
วอลนัท

คำตอบ:


8

ยกเว้นข้อยกเว้นบางประการที่คุณไม่ได้เป็นหนึ่งเรียกฟังก์ชันสมาชิกที่ไม่ใช่สมาชิก (เช่นassign) บนสตริงทำให้ตัวชี้ [... ] ชี้ไปที่ [... ] เป็นองค์ประกอบ นี้ละเมิดเงื่อนไขเกี่ยวกับassignว่า[s, s + n)เป็นช่วงที่ถูกต้องดังนั้นนี้เป็นพฤติกรรมที่ไม่ได้กำหนด

โปรดทราบว่าstring::operator=(string const&)มีภาษาโดยเฉพาะเพื่อทำการมอบหมายด้วยตนเองเป็นแบบไม่ใช้งาน


1
ดังนั้นสิ่งที่เป็นจุดของการทำให้เป็นโมฆะและจุดที่จำเป็นต้องมีในการถือ? ดูเหมือนว่าคำตอบจะถือว่าสมมติว่ามีเงื่อนไขก่อนที่จะเรียกฟังก์ชั่นสมาชิก
วอลนัท

1
@walnut ผมไม่มีภาษาทนายความ (ค่าคนที่มีการขยายโดยเฉพาะอย่างยิ่งความรู้ภาษา C ++) แต่เมื่อเราผกผันสถานการณ์ของคุณเราสามารถถามคำถาม - สามารถช่วงจะถูกยกเลิกในระหว่างการดำเนินการของassign? ถ้าใช่เราจะต้องกำหนดจุดเฉพาะในการใช้งานมอบหมายเพื่อทำเครื่องหมายเมื่อการทำให้เกิดความไม่ถูกต้องนั้นเกิดขึ้นจริงและฉันเชื่อว่านั่นไม่ใช่สิ่งที่ C ++ จะทำ ฉันอาจจะผิด
Fureeish

2
@Freeree ฉันไม่รู้เหมือนกัน แต่ดูเช่นปัญหา LWG 526ปิดเป็น " ไม่ใช่ข้อบกพร่อง " ซึ่งกล่าวถึงในคำแนะนำสำหรับการปิดที่std::vector::insert(iterator pos, const T& value)ต้องใช้งานหากvalueอยู่ในเวกเตอร์เองเพราะมาตรฐานไม่ได้ระบุว่า ได้รับอนุญาตไม่ทำงานแม้ว่าการอ้างอิงนั้นอาจถูกทำให้ใช้ไม่ได้
วอลนัท

1
@ วอลนัต " จำเป็นต้องใช้งานเพราะมาตรฐานไม่ได้รับอนุญาตเพราะไม่ได้ผล " - รักเลย Sooo ... มันคุ้มค่าที่จะถามว่าเกิดอะไรขึ้นในการฝึก ? การใช้งานจำเป็นต้องทำสำเนาของการโต้แย้งในสถานการณ์เช่นนี้หรือไม่? คุณจะนำไปใช้จริงได้อย่างไร .. ? ฉันเคยได้ยินเกี่ยวกับมาตรฐานที่ต้องการคอมไพเลอร์เพื่อทำสิ่งที่เป็นไปไม่ได้ - มันเป็นหนึ่งในกรณีเหล่านั้นหรือไม่? ขอบคุณสำหรับความคิดเห็น!
Fureeish

1
@Fureeish ที่จริงตัวอย่างก่อนหน้าของฉัน (ตอนนี้ถูกลบ) ไม่ได้ทดสอบสิ่งที่ฉันต้องการทดสอบ นี่คือตัวอย่างที่คงที่ซึ่งแสดงให้เห็นว่าทั้ง libc ++ และ libstdc ++ ทำสำเนาจริงก่อนที่จะย้ายตามการจัดสรรใหม่ตามต้องการ
วอลนัท
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.