Решено с помощью glibc 2.24 -- см. ОБНОВЛЕНИЕ ниже
Вот кусок C-кода (скомпилирован с помощью gcc 5.3.1, glibc 2.23):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
int main() {
const char* s1="Original content of file.\n"
"still original content and some remaining original content.\n";
const char* s2="overwriting data with new content\n";
const char* s3="appended data\n";
const size_t bufsz=strlen(s1)+1;
char buf[bufsz];
FILE *f;
int r;
f=fmemopen(buf,bufsz,"w");
assert(f!=NULL);
// setbuf(f, NULL); // variant no. 1
// setbuffer(f, buf, bufsz); // variant no. 2
r=fwrite(s1,strlen(s1),1,f);
assert(r==1);
r=fflush(f);
assert(r==0);
rewind(f);
r=fwrite(s2,strlen(s2),1,f);
assert(r==1);
r=fwrite(s3,strlen(s3),1,f);
assert(r==1);
r=fclose(f);
assert(r==0);
printf("%s",buf);
}
Он делает то, что я ожидаю. Вывод:
overwriting data with new content appended data and some remaining original content.
Теперь man-страница fmemopen(3) советует либо отключить буферизацию (раскомментировать вариант 1), либо явно установить
buf
в качестве буфера (раскомментировать вариант 2).Однако в обоих случаях я получаю в результате:
appended data ta with new content ginal content and some remaining original content.
Таким образом, добавленные данные не были записаны после второго содержимого, как ожидалось, а перезаписали второе содержимое.
Поведение остается прежним, если я открываю файл в двоичном режиме (т.е. заменяя режим «w» на «wb»).
valgrind не сообщает об ошибках (за исключением ложного срабатывания «Перекрытие источника и назначения» в случае буферизации. Последнее связано с попыткой записать в память буфер STDIO, который действительно является одним и тем же адресом.)
Что не так? Я сделал ошибку? Или это ошибка GLIBC?
ОБНОВИТЬ
4 августа вышла новая версия glibc 2.24. С gcc 5.4.0 и glibc 2.24, вариант №. 1 (небуферизованный ФАЙЛ) работает нормально. Вариант 2 (самобуферизованная версия) дает другой, но все же ошибочный результат. Таким образом, я считаю, что R.. прав, утверждая, что это ошибка документации на странице руководства fmemopen(3). Подниму отчет об ошибке...
fflush(f);
непосредственно перед перемоткой не меняет поведение ни в одном из вариантов. Возвращаемое значение fflush(f) равно 0 во всех случаях. - person ralfg   schedule 10.08.2016