0

全部,

我正在使用 MapViewOfFile 将文件的一部分保存在内存中。有一个流指向这个文件并写入它,然后被倒带。我使用指向映射文件开头的指针,并读取直到我到达作为最后一个字符写入的空字符。

int fd;
yyout = tmpfile();
fd = fileno(yyout);
#ifdef WIN32
    HANDLE fm;
    HANDLE h = (HANDLE) _get_osfhandle (fd);

    fm = CreateFileMapping(
             h,
             NULL,
             PAGE_READWRITE|SEC_RESERVE,
             0,
             4096,
             NULL);
    if (fm == NULL) { 
            fprintf (stderr, "%s: Couldn't access memory space! %s\n", argv[0],  strerror (GetLastError()));
            exit(GetLastError());
    }
    bp = (char*)MapViewOfFile(
              fm,
              FILE_MAP_ALL_ACCESS,
              0,
              0,
              0);
    if (bp == NULL) { 
            fprintf (stderr, "%s: Couldn't fill memory space! %s\n", argv[0],  strerror (GetLastError()));
            exit(GetLastError());
    }

数据被发送到yyout流中,直到flushData()被调用。这会将 null 写入流,刷新,然后倒回流。然后我从映射内存的开头开始,读取字符,直到我到达空值。

void flushData(void) {
    /* write out data in the stream and reset */ 
    fprintf(yyout, "%c%c%c", 13, 10, '\0');
    fflush(yyout);
    rewind(yyout);
    if (faqLine == 1) {
        faqLine = 0; /* don't print faq's to the data file */
    }
    else {
        char * ps = bp;
        while (*ps != '\0') {
                fprintf(outstream, "%c%c", *ps, blank);
                ps++;
            }
        fflush(outfile);
    }
    fflush(yyout);
    rewind(yyout);
}

刷新后,更多的数据被写入流,应该设置在内存区域的开头。就我可以用 gdb 确定的那样,流没有被倒带,并最终填满了分配的空间。

由于流指向底层文件,因此最初不会导致问题。但是,当我尝试遍历内存时,我从来没有找到空值。这导致一个SIGSEV. 如果您想了解我为什么需要它的更多详细信息,请参见此处

为什么我没有按预期重用内存空间?

4

3 回答 3

4

我认为 CreateFileMapping 的 MSDN 文档中的这一行可能是线索。

映射文件和使用输入和输出 (I/O) 函数(ReadFile 和 WriteFile)访问的文件不一定是一致的。

您显然没有使用 Read/WriteFile,但应该根据映射视图与显式 I/O 调用来理解文档。无论如何,C RTL 肯定是使用 Win32 API 实现的。

简而言之,这种方法是有问题的。

我不知道为什么更改视图/文件大小会有所帮助;也许它只是将未定义的行为转移到恰好有益的方向。

于 2012-04-26T23:26:13.120 回答
0

好吧,在研究了一段时间之后,我有了一个可行的解决方案。我不知道为什么会成功,所以如果有人想出更好的东西,我会很乐意接受他们的答案。

fm = CreateFileMapping(
         h,
         NULL,
         PAGE_READWRITE|SEC_RESERVE,
         0,
         16384,
         NULL);

如您所见,唯一的变化是从4096to声明的大小16384。我不知道为什么当一次输入的总字符数不超过 1200 时这会起作用。如果有人可以提供这方面的详细信息,我将不胜感激。

于 2012-04-26T20:09:42.340 回答
0

完成地图后,只需取消地图即可。

UnmapViewOfFile(bp);
于 2016-07-08T00:11:51.237 回答