0

All,

I'm using MapViewOfFile to hold part of a file in memory. There is a stream that points to this file and writes to it, and then is rewound. I use the pointer to the beginning of the mapped file, and read until I get to the null char I write as the final character.

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());
    }

Data is sent to the yyout stream, until flushData() is called. This writes a null to the stream, flushes, and then rewinds the stream. Then I start from the beginning of the mapped memory, and read chars until I get to the 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);
}

After flushing, more data is written to the stream, which should be set to the start of the memory area. As near as I can determine with gdb, the stream is not getting rewound, and eventually fills up the allocated space.

Since the stream points to the underlying file, this does not cause a problem initially. But, when I attempt to walk the memory, I never find the null. This leads to a SIGSEV. If you want more details of why I need this, see here.

Why am I not reusing the memory space as expected?

Community
  • 1
  • 1
Spencer Rathbun
  • 14,510
  • 6
  • 54
  • 73
  • What are you trying to achieve? Why does the code not also unmap the view and close the handle? – 0xC0000022L Apr 26 '12 at 18:50
  • @STATUS_ACCESS_DENIED this is just a snippet of the code base, after I'm done using the mapped space, I unmap it and and close the handle. The point is to redirect a file stream into memory on a windows system. – Spencer Rathbun Apr 26 '12 at 19:02

3 Answers3

4

I think this line from the MSDN documentation for CreateFileMapping might be the clue.

A mapped file and a file that is accessed by using the input and output (I/O) functions (ReadFile and WriteFile) are not necessarily coherent.

You're not apparently using Read/WriteFile, but the documentation should be understood in terms of mapped views versus explicit I/O calls. In any case, the C RTL is surely implemented using the Win32 API.

In short, this approach is problematic.

I don't know why changing the view/file size helps; perhaps it just shifts the undefined behaviour in a direction that happens to be beneficial.

dave
  • 131
  • 2
  • I was worried about that. At this point the thing works and I've run out of time to track this down. Until it leaps up and bites somebody, mngmt. wants me to move on. Unless, of course, someone comes up with a solution... – Spencer Rathbun Apr 27 '12 at 12:27
0

Well, after working on this for a while, I have a working solution. I don't know why this succeeds, so if someone comes up with something better, I'll be happy to accept their answer instead.

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

As you can see, the only change is to the size declared from 4096 to 16384. Why this works when the total chars input at a time is no more than 1200, I don't know. If someone could provide details on this, I would appreciate it.

Spencer Rathbun
  • 14,510
  • 6
  • 54
  • 73
0

When you're done with the map, simply un-map it.

UnmapViewOfFile(bp);
The SE I loved is dead
  • 1,517
  • 4
  • 23
  • 27