2017-07-20 12 views
0

Je joue avec les "nouvelles" fonctions stdio mentionnées dans la norme c11: open_memstream et fmemopen.Pourquoi setbuf se bloque avec le fichier open_memstream?

sur Ubuntu 16.10 Compiler avec gcc ou sur Rextester avec clang (voir lien ci-dessous)

size_t sizeloc = 0; char *bufloc = NULL; 
FILE *mf = open_memstream (&bufloc, &sizeloc); 
setbuf(mf, NULL); // this crashes 

Appel setbuf pour le mode unbuffered sur un fichier créé avec open_memstream lancers francs SIGSEGV. (Je veux définir le mode unbuffered plutôt que d'appeler fflush après chaque écriture.) A propos, fflush marche.)

Pourquoi setbuf (mf, NULL) se bloque? Qu'est-ce que je fais mal? Dans un fichier renvoyé par l'autre fonction, fmemopen, setbuf(mf, NULL) fonctionne et semble fonctionner comme prévu.

link to my example @rextester

+1

Je ne sais pas d'où vous obtenez ceci, mais les deux fonctions ne sont définitivement pas C11. Ils sont POSIX 2008, et non pris en charge sur d'autres systèmes, je pense. Ils n'ont donc pas grand chose à voir avec C99 ou C11. Je supprime ces drapeaux et ajoute POSIX. –

+0

Essayer de modifier le comportement de mise en mémoire tampon d'une fonction qui fonctionne entièrement dans la mémoire semble étrange. Ne pensez-vous pas que le fournisseur de votre implémentation a déjà optimisé cela autant que possible? La modification de la mise en mémoire tampon des fichiers qui correspondent aux périphériques est logique car ils peuvent être lents (latence ou débit), mais ici, cela n'en fait pas. De plus, vous ne pouvez accéder au tampon résultant qu'après un 'fflush'. –

+0

Merci Jens. En fait, ce que je m'attendais à ce que ces flux de mémoire mappés soient sans tampon et leur mémoire de sauvegarde contienne immédiatement le résultat de la dernière écriture. Mais ce n'est pas le cas. Une chasse d'eau est nécessaire. C'est pourquoi j'ai essayé de définir le mode unbuffered, et il semble fonctionner avec l'un d'entre eux. – ddbug

Répondre

1

à proprement parler, ce que vous essayez de faire est pas pris en charge par POSIX. Il est également inutile parce que la spécification pour open_memstream dit essentiellement qu'il n'y a pas de mise en mémoire tampon (du moins je pense que c'est l'intention).

Il semble à la fois open_memstream et fmemopen ont été ajoutés à POSIX sans tenir compte de l'interaction avec les interfaces existantes. La description de setvbuf a été copié de la norme C et n'a pas mis à jour et dit:

Le setvbuf() fonction peut être utilisé après que le flux pointé par flux est associé à un fichier ouvert, mais avant toute autre opération [...]

Cela implique que l'utilisation de cette fonction pour les nouveaux flux ne serait pas autorisée car il n'y a pas de fichier associé. Mais je pense que c'est vraiment un accident, et l'interaction avec open_memstream et fmemopen a été simplement manquée. La même chose s'est produite du côté de la mise en œuvre, où ce cas d'utilisation n'était pas non plus pris en compte, alors la glibc se bloque ici.

De même, il n'est pas clair si fflush (NULL) devrait avoir un impact sur les flux qui ne sont pas sauvegardés par des fichiers.

+0

Florian.Dans mon exemple, j'ai fflush sur le descripteur FICHIER des deux types de "fichiers mémoire" et cela fonctionne (avant d'appeler fflush la mémoire de sauvegarde est vide, après fflush il contient ce qui est attendu). Mais le point est que je veux éviter. appeler fflush. – ddbug

+0

Ah, cas d'utilisation intéressant. Voulez-vous vous assurer que le pointeur et la valeur de taille que vous avez passés à 'open_memstream' sont toujours en cours par rapport à ce qui a été écrit dans le tampon? –

+0

Oui si possible. – ddbug