Neden C ++ standardı bu şekilde arama yapıyor?


17

C ++, streamoffbir (dosya) akışı içindeki bir ofseti temsil etmek için türü kullanır ve [stream.types] içinde aşağıdaki gibi tanımlanır:

using streamoff = implementation-defined ;

Streamoff türü, işletim sistemi için mümkün olan maksimum dosya boyutunu temsil etmek için yeterli büyüklükte imzalı temel integral türlerinden birinin eş anlamlısıdır. 287)

287) Genellikle uzun uzun.

Bu mantıklıdır çünkü büyük dosyalar içinde arama yapmaya izin verir (kullanımın aksine long, sadece 32 bit genişliğinde olabilir).

[filebuf.virtuals] basic_filebufbir dosyada arama işlevini aşağıdaki gibi tanımlar:

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

off_typeeşdeğeridir streamoff, bkz. [iostreams.limits.pos]. Ancak, standart fonksiyonun etkilerini açıklamaya devam eder. Son cümle beni rahatsız ediyor fseek:

Etkileri : widthBelirtelim a_codecvt.encoding(). Eğer is_open() == false, veya off != 0 && width <= 0, daha sonra yerleştirme işlemi başarısız olur. Aksi takdirde, eğer way != basic_ios::curveya off != 0son işlem çıktıysa, çıktı sırasını güncelleyin ve herhangi bir kaydırma sırasını yazın. Sonra, yeni pozisyonu width > 0arayın : if , call fseek(file, width * off, whence), aksi takdirde call fseek(file, 0, whence).

fseekbir longparametreyi kabul eder . Eğer off_typeve streamoffolarak tanımlanır long long(standart önerdiği gibi), bu bir aşağı dönüştürme yol açabilir longçağrılırken fseek(file, width * off, whence)(böcek teşhis etmek potansiyel zor yol açan). Bu, streamofftürü ilk etapta tanıtmanın tüm mantığını sorgulamaktadır .

Bu kasıtlı mı yoksa standartta bir kusur mu?


8
kusur benziyor.
Yakk - Adam Nevraumont

Ben gcc libstdc ++ fseeko64 kullandığını düşünüyorum .
KamilCuk

1
Offhand, kaputun altında seekoffmutlaka kullanılması gibi görünmüyor fseek. Bunun yerine, (muhtemelen bilindik?) Davranışı fseekne seekoffyaptığını açıklamak için kullanılır .
jjramsey

@jjramsey Bu da benim izlenimimdi. Bununla birlikte, ifade biçimi, bir açıklama yerine bir gereklilik öneriyor gibi görünmektedir.
jceed2

1
@jjramsey "Efektler" kısmının fseek, aynı etkiye sahip bir şey yaptığı sürece gerçekten çağırmak zorunda olmadığı anlamına gelebilecek şekilde yorumlanabileceğini kabul ediyorum . Ancak fseek, bir ofsetten daha az LONG_MINveya daha büyük bir ofsetin bir LONG_MAXetkisi yoktur, bu nedenle açıklama en azından eksiktir, en azından streamoffdaha geniş olan uygulamalar için long.
Keith Thompson

Yanıtlar:


6

Bundan çizim yaptığınız, C ++ akışları arasında bir uyumsuzluk olduğu ve fseekçalışma zamanı hatalarına yol açacağı sonucunun yanlış olduğunu düşünüyorum. Durum şöyle görünüyor:

  1. long64 bit olan sistemlerde , streamoffolarak tanımlanır longve seekoffişlev çağrılır fseek.

  2. Sistemlerde nerede long32 bit ama işletim sistemi destekleri 64 bit dosya uzaklıklar olduğu streamoffgibi tanımlanır long longve seekoffya adlandırılan bir fonksiyon çağırmaktadır fseekoveya fseeko64bu 64-bit ofset kabul eder.

İşte seekoffbenim Linux sistemimin tanımından snippet :

#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, Büyük Dosya Desteği anlamına gelir .

Sonuç: Standart, streamoff gereksinimi olduğunu o görünüşte çatışmalar seekoffçağırmak fseek, kütüphane tasarımcıları onlar varyantı çağırmalıdır anlıyoruz fseekbu işletim desteklerin olduğunu uzaklıklar dizi kabul eder.


@ypnos İndirmedim ve bu cevabı faydalı buluyorum. Sanırım birisi önemini yitirdi çünkü konuyu kaçırıyor. Sorun, bu konuda standardı görmezden gelen aklı başında uygulamalar olmadığı için sorun, uygulamanın akılcı olması için standardın göz ardı edilmesi gerektiğidir.
jceed2

6
The situation seems to be:- Durum uygulaması çağırmak için değil izin verilmez olmasıdır fseekiçinde seekoff. Aramalı fseek, değil, standart diyor. Bu uygulamanın geçersiz olduğunu iddia edebilirim. Soruyu cevaplamadığına inanıyorum. Och, llvm buldu , çağırıyor fseeko.
KamilCuk

Tıpkı bir FYI gibi, VC ++ _fseeki64bu işlevi çağırır ; bu da standardın söylediklerini ihlal ediyor gibi görünüyor.
ChrisMM

1
Bu, sorunu fark eden ve standardı göz ardı eden uygulayıcıların bir örneğidir. Onlar sevindim, ama standart gerçekten düzeltilmesi gerekiyor.
NathanOliver

1
Bazı insanlar standardı tam anlamıyla alıyorlar. Uygulamanın tam anlamıyla çağrılan bir işlevi çağırması zor değildir fseek. Başka bir yerde standart, bir şeyi "arayarak sanki" olarak tanımlar fseek(...). Kelimenin tam anlamıyla aramakla çok ilgiliyse fseek, bu ifade farklı olurdu. C ++ kütüphanesi uygulasaydınız, cidden, ne yapardınız? fseekBir belge size söylediği için 64 bitlik bir dosya ofsetinin en düşük 32 bitiyle arama yapmakta ısrar eder misiniz? Müşterileriniz bunun için teşekkür eder mi?
Willis Blackburn
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.