web-dev-qa-db-fra.com

Pourquoi le standard C ++ gère-t-il le fichier en cherchant comme il le fait?

C++ utilise le type streamoff pour représenter un décalage dans un flux (de fichier) et est défini comme suit dans [stream.types]:

using streamoff = implementation-defined ;

Le type streamoff est synonyme de l'un des types intégraux de base signés de taille suffisante pour représenter la taille de fichier maximale possible pour le système d'exploitation. 287)

287) Typiquement longue et longue.

Cela a du sens, car il permet de rechercher dans des fichiers volumineux (par opposition à l'utilisation de long, qui ne peut avoir qu'une largeur de 32 bits).

[filebuf.virtuals] définit la fonction de basic_filebuf pour rechercher dans un fichier comme suit:

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

off_type Est équivalent à streamoff, voir [iostreams.limits.pos]. Cependant, la norme explique ensuite les effets de la fonction. Je suis irrité par la toute dernière phrase, qui nécessite un appel à fseek:

Effets: Soit width désigne a_codecvt.encoding(). Si is_open() == false ou off != 0 && width <= 0, L'opération de positionnement échoue. Sinon, si way != basic_ios::cur Ou off != 0, Et si la dernière opération a été sortie, mettez à jour la séquence de sortie et écrivez toute séquence non décalée. Ensuite, recherchez la nouvelle position: si width > 0, Appelez fseek(file, width * off, whence), sinon appelez fseek(file, 0, whence).

fseek accepte un paramètre long. Si off_type Et streamoff sont définis comme long long (Comme suggéré par la norme), cela pourrait conduire à une conversion vers le bas en long lors de l'appel de la fonction fseek(file, width * off, whence) (conduisant à des bogues potentiellement difficiles à diagnostiquer). Cela remet en question toute la justification de l'introduction du type streamoff en premier lieu.

Est-ce intentionnel ou un défaut dans la norme?

17
jceed2

Je pense que la conclusion que vous tirez de cela, qu'il existe une incompatibilité entre les flux C++ et fseek qui entraînera des bogues d'exécution, est incorrecte. La situation semble être:

  1. Sur les systèmes où long est 64 bits, streamoff est défini comme long et la fonction seekoff appelle fseek.

  2. Sur les systèmes où long est 32 bits mais le système d'exploitation prend en charge les décalages de fichiers 64 bits, streamoff est défini comme long long et seekoff invoque une fonction appelée fseeko ou fseeko64 qui accepte un décalage 64 bits.

Voici un extrait de la définition de seekoff sur mon système 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 signifie Large File Support .

Conclusion: Bien que la norme suggère une définition de streamoff qui soit ostensiblement en conflit avec l'exigence que seekoff invoque fseek, les concepteurs de bibliothèques comprennent qu'ils doivent appeler la variante de fseek qui accepte la gamme complète des décalages pris en charge par le système d'exploitation.

6
Willis Blackburn