2017-07-20 94 views
0

我在玩c11标准中提到的“新”stdio功能:open_memstreamfmemopen为什么setbuf与open_memstream文件崩溃?

编译在Ubuntu 16.10用gcc或Rextester与铛(见下面的链接),用于缓冲模式

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

调用函数setbuf与open_memstream抛出SIGSEGV创建的文件。 (我想设置无缓冲模式,而不是在每次写入后调用fflush。顺便说一下,fflush的工作原理。)

为什么setbuf(mf,NULL)崩溃?我做错了什么?

对其他函数返回的文件,fmemopen,setbuf(mf, NULL)的作品,似乎做了什么样的预期。

link to my example @rextester

+1

我不知道你从哪里得到这个,但是这两个函数肯定不是C11。他们是POSIX 2008,我认为在其他系统上不支持。所以他们与C99和C11都没什么关系。我删除这些标志并添加POSIX。 –

+0

试图改变完全在内存中工作的函数的缓冲行为听起来很奇怪。你不认为你的实现提供者已经尽可能地优化了吗?改变与设备相对应的文件的缓冲是有意义的,因为这些缓慢(延迟或吞吐量),但是在这里没有。另外,无论如何,你只能在'fflush'后面访问得到的缓冲区。 –

+0

谢谢Jens。实际上我预计这些内存映射流是无缓冲的,它们的后备内存立即包含最后一次写入的结果。但事实并非如此。需要冲洗。这就是为什么我试图设置无缓冲模式,并且似乎与其中一种模式一起工作的原因。 – ddbug

回答

1

严格地说,你试图做什么目前不支持POSIX。这也是没有必要的,因为open_memstream的规范基本上说没有缓冲(至少我认为这是意图)。

看起来open_memstreamfmemopen都被添加到POSIX中,而没有考虑与现有接口的交互。的setvbuf已经描述了从C标准复制和尚未更新并说:

setvbuf用来()之后的流指向由与打开的文件相关联的函数可以被使用,但在任何其他操作之前[012]

这意味着对于新的流使用此函数将不被允许,因为没有关联的文件。但我认为这真的是一个意外,与open_memstreamfmemopen的互动完全没有。在实现方面也发生了同样的事情,因为这个用例没有被考虑,所以glibc在这里崩溃。

同样,fflush (NULL)是否应该对未被文件支持的流有影响尚不清楚。

+0

弗洛里安。在我的例子中,我做了两种类型的“内存文件”的FILE描述符,它可以工作(在调用fflush之前,后备内存为空,在fflush包含预期内容之后)。但重点是我想避免。打电话给fflush。 – ddbug

+0

啊,有趣的用例。你是否想要确保传递给'open_memstream'的指针和大小值对于写入缓冲区的内容始终是最新的? –

+0

如果可能的话。 – ddbug