เหตุใดไฟล์จัดการมาตรฐาน C ++ จึงหาวิธีการใช้งาน


17

C ++ ใช้streamoffชนิดเพื่อแสดงออฟเซ็ตภายในสตรีม (ไฟล์) และกำหนดไว้ดังนี้ใน [stream.types]:

using streamoff = implementation-defined ;

ประเภท streamoff เป็นคำพ้องความหมายสำหรับหนึ่งในประเภทอินทิกรัลพื้นฐานที่ลงนามแล้วซึ่งมีขนาดเพียงพอที่จะแสดงขนาดไฟล์สูงสุดที่เป็นไปได้สำหรับระบบปฏิบัติการ 287)

287) ความยาวโดยทั่วไป

สิ่งนี้สมเหตุสมผลเนื่องจากอนุญาตให้ค้นหาไฟล์ขนาดใหญ่ (ต่างจากการใช้longซึ่งอาจมีความกว้างเพียง 32 บิต)

[filebuf.virtuals] กำหนดbasic_filebufฟังก์ชั่นของการค้นหาภายในไฟล์ดังนี้:

pos_type seekoff(off_type off, ios_base::seekdir way, ios_base::openmode which = ios_base::in | ios_base::out) override;

off_typeเทียบเท่ากับstreamoffดู [iostreams.limits.pos] อย่างไรก็ตามมาตรฐานก็จะอธิบายผลกระทบของฟังก์ชั่น ฉันรู้สึกหงุดหงิดกับประโยคสุดท้ายที่ต้องเรียกร้องให้fseek:

ผลกระทบ : อนุญาตwidthแสดงa_codecvt.encoding()ว่า หากis_open() == falseหรือoff != 0 && width <= 0จากนั้นการดำเนินการกำหนดตำแหน่งจะล้มเหลว มิฉะนั้นถ้าway != basic_ios::curหรือoff != 0หากการดำเนินการครั้งสุดท้ายเป็นผลลัพธ์ให้อัปเดตลำดับเอาต์พุตและเขียนลำดับ unshift ใด ๆ ถัดไปขอไปยังตำแหน่งใหม่: ถ้าwidth > 0โทรมิฉะนั้นโทรfseek(file, width * off, whence)fseek(file, 0, whence)

fseekยอมรับlongพารามิเตอร์ หากoff_typeและstreamoffถูกกำหนดเป็นlong long(ตามที่แนะนำโดยมาตรฐาน) สิ่งนี้อาจนำไปสู่การแปลงลงเป็นlongเมื่อโทรfseek(file, width * off, whence)(นำไปสู่การยากที่จะวินิจฉัยข้อบกพร่อง) คำถามนี้เกี่ยวกับเหตุผลทั้งหมดสำหรับการแนะนำstreamoffประเภทในตอนแรก

นี่เป็นเจตนาหรือข้อบกพร่องในมาตรฐานหรือไม่?


8
ข้อบกพร่องดูเหมือนว่า
Yakk - Adam Nevraumont

ฉันคิดว่าฉันเห็นว่า GCC libstdc ++ ใช้fseeko64
KamilCuk

1
Offhand มันดูไม่เหมือนที่seekoffจำเป็นต้องใช้ fseekภายใต้ประทุน แต่พฤติกรรมที่คุ้นเคย (สันนิษฐาน?) ของfseekใช้เพื่ออธิบายสิ่งที่seekoffกำลังทำ
jjramsey

@jjramsey นี่เป็นความประทับใจของฉันเช่นกัน อย่างไรก็ตามวิธีการใช้ถ้อยคำดูเหมือนจะแนะนำข้อกำหนดมากกว่าคำอธิบาย
jceed2

1
@ jjramsey ฉันยอมรับว่าส่วน "เอฟเฟกต์" สามารถตีความได้อย่างสมเหตุสมผลว่าหมายความว่าไม่จำเป็นต้องโทรหาfseekตราบใดที่มันมีผลแบบเดียวกัน แต่fseekด้วยการชดเชยน้อยกว่าLONG_MINหรือมากกว่าLONG_MAXไม่มีผลดังนั้นคำอธิบายที่ดีที่สุดที่ไม่สมบูรณ์อย่างน้อยสำหรับการใช้งานที่กว้างกว่าstreamoff long
Keith Thompson

คำตอบ:


6

ฉันคิดว่าข้อสรุปที่คุณวาดมาจากสิ่งนี้ว่ามีความไม่ตรงกันระหว่างสตรีม C ++ และfseekที่จะนำไปสู่ข้อผิดพลาดรันไทม์ไม่ถูกต้อง สถานการณ์ดูเหมือนจะเป็น:

  1. ในระบบที่longเป็น 64 บิตstreamoffถูกกำหนดให้เป็นlongและจะเรียกฟังก์ชั่นseekofffseek

  2. บนระบบที่longมี 32 บิต แต่ระบบปฏิบัติการรองรับการออฟเซ็ตไฟล์ 64 บิตstreamoffถูกกำหนดเป็นlong longและseekoffเรียกใช้ฟังก์ชันที่เรียกว่าอย่างใดอย่างหนึ่งfseekoหรือfseeko64ที่ยอมรับออฟเซ็ต 64 บิต

นี่คือตัวอย่างจากคำจำกัดความของseekoffบนระบบ Linux ของฉัน:

#ifdef _GLIBCXX_USE_LFS
    if (!fseeko64(_M_file, __off, __whence))
      __ret = std::streampos(ftello64(_M_file));
#else
    if (!fseek(_M_file, __off, __whence))
      __ret = std::streampos(std::ftell(_M_file));
#endif

LFS ย่อมาจากการสนับสนุนไฟล์ขนาดใหญ่

สรุป: ในขณะที่มาตรฐานชี้ให้เห็นคำนิยามสำหรับstreamoffความขัดแย้งที่ขัดแย้งกับข้อกำหนดที่seekoffเรียกใช้fseekนักออกแบบห้องสมุดเข้าใจว่าพวกเขาจะต้องเรียกสิ่งที่แตกต่างfseekว่ายอมรับการชดเชยเต็มรูปแบบที่ระบบปฏิบัติการรองรับ


@ypnos ฉันไม่ได้ลงคะแนนและฉันคิดว่าคำตอบนี้มีประโยชน์ ฉันเดาใครบางคนที่ลงคะแนนเพราะมันพลาดจุด ปัญหาไม่ใช่ว่าจะมีการใช้งานที่มีสติซึ่งเพิกเฉยต่อมาตรฐานในเรื่องนี้ปัญหาคือว่ามาตรฐานจะต้องถูกละเว้นเพื่อให้การใช้งานมีสติ
jceed2

6
The situation seems to be:- สถานการณ์ว่าการดำเนินการไม่ได้รับอนุญาตจะไม่เรียกในfseek seekoffมันต้องเรียกfseekมันไม่ได้มาตรฐานบอกว่าต้องทำ ฉันสามารถยืนยันว่าการใช้งานนี้ไม่ถูกต้อง ฉันเชื่อว่ามันไม่ตอบคำถาม Och พบLLVMfseekoมันเรียก
KamilCuk

ในฐานะที่เป็น FYI นั้น VC ++ จะเรียก_fseeki64ใช้ฟังก์ชันนี้ ซึ่งดูเหมือนว่าจะละเมิดสิ่งที่มาตรฐานพูด
ChrisMM

1
นี่เป็นกรณีที่ผู้ใช้งานตระหนักถึงปัญหาและเพิกเฉยต่อมาตรฐาน ฉันดีใจที่พวกเขาทำ แต่มาตรฐานจะต้องได้รับการแก้ไขจริงๆ
NathanOliver

1
บางคนก็ยึดถือมาตรฐานอย่างแท้จริงเช่นกัน fseekมันไม่ได้เรียกร้องให้ดำเนินการอย่างแท้จริงเรียกฟังก์ชั่นที่เรียกว่า ที่อื่น ๆ มาตรฐานอธิบายบางสิ่งบางอย่างเป็น "ราวกับว่าโดยการโทรfseek(...)." ถ้ามันสนใจเรื่องการโทรfseekมามาก อย่างจริงจังคุณจะทำอะไรถ้าคุณใช้ห้องสมุด C ++? คุณจะยืนยันในการโทรfseekด้วยออฟเซ็ตไฟล์ 64 บิตที่ต่ำกว่า 32 บิตเพราะเอกสารบอกให้คุณทราบหรือไม่? ลูกค้าของคุณจะขอบคุณสำหรับสิ่งนั้นหรือไม่
Willis Blackburn
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.