简体   繁体   中英

Writing to a memory mapped text file printing NULL till the end of mapped memory

In this code, Im writing some text to a memory mapped text file. Data is written to the file successfully, but when i open it with notepad, after the written data, "NULL" is repeatedly written upto the mapped memory limit which is greater than the text i have written.

What could be the possible reason?

pLogMsg = (char*)calloc(1024,sizeof(char));
printf("[INFO] entering logger writeback thread\n");

log_file = CreateFile (TEXT("one.txt"),             // Open one.txt.
                    GENERIC_READ | GENERIC_WRITE,   // Open for reading and writing
                    FILE_SHARE_WRITE,               // file share
                    NULL,                           // No security
                    OPEN_ALWAYS,                    // Open or create
                    FILE_ATTRIBUTE_NORMAL,          // Normal file
                    NULL);                          // No template file
if (log_file == INVALID_HANDLE_VALUE)
{
    printf("%d [ERR] cant open file GLE %d\n",GetCurrentThreadId(),GetLastError());
    return -1;
}
hMapping = CreateFileMapping( log_file, 0, PAGE_READWRITE, 0,4096 ,0 );
if (hMapping == INVALID_HANDLE_VALUE)
{
    printf("%d [ERR] cant create file mapping %d\n",GetCurrentThreadId(),GetLastError());
    return -1;
}
pFileData = (CHAR*)MapViewOfFile( hMapping, FILE_MAP_ALL_ACCESS, 0,0, 0 );
if (pFileData == NULL)
{
    printf("%d [ERR] cant mapview of file %d\n",GetCurrentThreadId(),GetLastError());
    return -1;
}
pLogMsg = LogPrint();//returns a null terminated string
memcpy(pFileData,pLogMsg,strlen(pLogMsg));
pFileData += strlen(pLogMsg); 
free(pLogMsg);

There is no 'end of file' marker within the file. You need to set the file length, so the OS marks it correctly.

See MSDN documentation for SetEndOfFile

Sets the physical file size for the specified file to the current position of the file pointer.

You cannot set the end-of-file marker through a file mapping. The end-of-file marker does not physically exist in a file. It is a flag raised by the OS when reading past the end of a file.

To set the size of a file you will have to call SetFilePointer followed by SetEndOfFile on the file object used to create the file mapping.

first of all CreateFileMapping and MapViewOfFile this is bad solution for log file. you need create/open file with FILE_APPEND_DATA access instead GENERIC_READ | GENERIC_WRITE GENERIC_READ | GENERIC_WRITE - so call must look like:

HANDLE log_file = CreateFileW(L"one.txt", 
    FILE_APPEND_DATA,
    FILE_SHARE_WRITE|FILE_SHARE_READ,     
    NULL,
    OPEN_ALWAYS,                 
    FILE_ATTRIBUTE_NORMAL,   
    NULL);

in this case you open file with FILE_APPEND_DATA and SYNCHRONIZE (because no FILE_FLAG_OVERLAPPED ):

If the caller sets only the FILE_APPEND_DATA and SYNCHRONIZE flags, it can write only to the end of the file, and any offset information about write operations to the file is ignored. The file will automatically be extended as necessary for this type of operation.

after this you need log via WriteFile - it will be automatically append to the end of file. this is what exactly need for log file.

however, if want use CreateFileMapping and MapViewOfFile - at first CreateFileMapping return 0 on error, so check if (hMapping == INVALID_HANDLE_VALUE) is wrong

if you want change file size - you need use for this SetFileInformationByHandle with FileEndOfFileInfo (vista+)or NtSetInformationFile with FileEndOfFileInformation (working everywhere, how not hard understand SetFileInformationByHandle is only very thin shell over NtSetInformationFile or ZwSetInformationFile (in user mode this is the same function)). use SetFilePointer followed by SetEndOfFile also possible but bad and not effective choice - you will be have 2 calls in src code instead on single. in binary - you will even more worse situation: first you set file position, that SetEndOfFile read this file position and finally call NtSetInformationFile with this position. so 3 calls instead one. and assume that nobody change file position (on this handle) between SetFilePointer and SetEndOfFile calls

but need clear understand that call SetFileInformationByHandle with FileEndOfFileInfo you can only after you unmap view and close section. otherwise you got error ERROR_USER_MAPPED_FILE ( STATUS_USER_MAPPED_FILE )

If CreateFileMapping is called to create a file mapping object for hFile, UnmapViewOfFile must be called first to unmap all views and call CloseHandle to close the file mapping object before you can call SetEndOfFile .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM