Lorsque vous mappez () un fichier texte, comme ça
int fd = open("file.txt", O_RDWR); fstat(fd, &sb) char *text = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
le contenu du fichier est mappé directement dans la mémoire, et le text
qu’il contient ne contiendra pas de terminateur NUL, de sorte qu’il ne serait pas sûr de l’utiliser avec des fonctions de chaîne normales. Sur Linux (au moins), les octets restants de la page inutilisée sont remplis de zéro, si bien que vous obtenez un terminateur NUL dans tous les cas où la taille du fichier n’est pas un multiple de la taille de la page.
Mais compter sur ce qui semble sale et les autres implémentations de mmap()
par exemple, dans FreeBSD, je pense) ne remplissent pas les pages partielles. Les fichiers de mappage qui sont des multiples de la taille de la page seront également dépourvus du terminateur NUL.
Existe-t-il des moyens raisonnables de contourner ce problème ou d’append le terminateur NUL?
Les choses que j’ai considérées
strn*()
fonctionne exclusivement et suivre la distance jusqu’à la fin du tampon.
str*()
n’ont pas de strn*()
, comme strstr
. str*()
MAP_FIXED
n’est pas thread-safe; Semble un hack terrible de toute façon mmap()
un octet supplémentaire et rendre la carte inscriptible, et écrire le terminateur NUL. La page de manuel mmap de OpenGroup indique que vous pouvez créer un mappage plus grand que la taille de votre object, mais que l’access aux données en dehors de l’object mappé génèrera un SIGBUS
.
str*()
SIGBUS
, ce qui pourrait signifier que quelque chose d’autre s’est passé. Je ne suis pas vraiment sûr que l’écriture du terminateur NUL fonctionnera? ftruncate()
d’un octet.
str*()
; ftruncate()
va écrire un octet NUL dans la zone nouvellement allouée pour vous mmap()
qui ne remplissent pas les pages partielles read()
le fichier dans une mémoire de malloc()
et d’oublier mmap()
malloc()
et octet supplémentaire pour NUL mmap()
La solution n ° 1 semble généralement la meilleure et nécessite juste un travail supplémentaire de la part des fonctions de lecture du texte.
Existe-t-il de meilleures alternatives ou s’agit-il des meilleures solutions? Y a-t-il des aspects de ces solutions que je n’ai pas envisagés qui les rendent plus ou moins attrayants?
Je suggère de subir un changement de paradigme ici.
Vous regardez l’univers entier constitué de chaînes délimitées par des ‘\ 0’ qui définissent votre texte. Au lieu de regarder le monde de cette façon, pourquoi n’essayez-vous pas de regarder le monde où le texte est défini comme une séquence définie par un début et un iterator de fin.
Vous mmap
votre fichier, puis définissez initialement l’iterator de début, appelez-le beg_iter
au début du segment mmap-ed, et l’iterator de fin, appelez-le end_iter
, au premier octet suivant le dernier octet du segment mmap-ed, ou beg_iter+number_of_pages*pagesize
, puis jusqu’à
A) end_iter
est égal à beg_iter
, ou
B) beg_iter[-1]
n’est pas un caractère nul, alors
C) décrémenter end_iter
et revenir à l’étape A.
Lorsque vous avez terminé, vous avez une paire d’iterators, la valeur de l’iterator de début et la valeur de l’iterator de fin qui définit votre chaîne de texte.
Bien sûr, dans ce cas, vos iterators sont des caractères simples char *
, mais ce n’est vraiment pas très important. Ce qui est important, c’est que vous vous retrouviez maintenant avec un riche ensemble d’algorithmes et de modèles de la bibliothèque standard C ++ à votre disposition, qui vous permettent d’implémenter de nombreuses opérations compliquées, mutables (comme std::transform
), et non mutables ( comme std::find
).
Les chaînes terminées par un point nul sont vraiment un gage de l’époque du simple C. Avec C ++, les chaînes terminées par un caractère nul sont quelque peu archaïques et banales. Le code C ++ moderne devrait utiliser std::ssortingng
objects std::ssortingng
et les séquences définies par les iterators de début et de fin.
Une petite note en bas de page: au lieu de déterminer combien de padding NULL
vous avez fini avec mmap-ing (), vous pourriez trouver plus facile de fstat () le fichier et d’obtenir la longueur exacte du fichier, en octets, avant de le mapper. Ensuite, vous saurez maintenant exactement ce qui a été fait, et vous n’avez pas à l’inverser, en regardant le remplissage.