我正在尝试从使用fmemopenchar *创建的流中读取宽字符。

char *s = "foo bar foo";
FILE *f = fmemopen(s,strlen(s),"r");

wchar_t c = getwc(f);
getwc引发了段错误,我使用GDB进行了检查。

我知道这是由于使用 fmemopen 打开流导致的,因为在打开的流上调用getwc通常可以正常工作。

是否有fmemopen的宽字符版本,或者有其他方法可以解决此问题?

最佳答案

第二行应读取FILE *f = fmemopen(s, strlen(s), "r");。如前所述,fmemopen具有未定义的行为,并且可能返回NULL,这会导致getwc()崩溃。

更改fmemopen()行并添加对NULL的检查可解决崩溃问题,但不符合OP的目标。

似乎至少在GNU C库中,使用fmemopen()打开的流不支持宽方向。请注意,fmemopen在C标准中未定义,但在POSIX.1-2008中定义,并且在许多系统(如OS/X)上不可用。

这是程序的更正和扩展版本:

#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>

int main(void) {
    const char *s = "foo bar foo";
    FILE *f = fmemopen((void *)s, strlen(s), "r");
    wchar_t c;

    if (f == NULL) {
        printf("fmemopen failed: %s\n", strerror(errno));
        return 1;
    }
    printf("default wide orientation: %d\n", fwide(f, 0));
    printf("selected wide orientation: %d\n", fwide(f, 1));
    while ((c = getwc(f)) != WEOF) {
        printf("read %lc (%d 0x%x)\n", c, c, c);
    }
    return 0;
}

在linux上运行:
default wide orientation: -1
selected wide orientation: -1

没有输出,WEOF立即返回。

linux手册页中fwide(f, 0)的说明:


fmemopen()返回的流是面向字节的,不能更改为面向宽字符。

10-06 02:27