2011-03-20 43 views
2

請看下面的代碼。內存映射文件的奇怪行爲,一些觀察和一些問題

#include <windows.h> 

void Write(char *pBuffer) 
{ 
// pBuffer -= 4*sizeof(int); 
    for(int i = 0; i<20; i++) 
     *(pBuffer + sizeof(int)*i) = i+1; 
} 

void main() 
{ 
    HANDLE hFile = ::CreateFile("file", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 

    if(INVALID_HANDLE_VALUE == hFile) 
    { 
     ::MessageBox(NULL, "", "Error", 0); 
     return; 
    } 

    HANDLE hMMF = ::CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 32, NULL); 

    char *pBuffer = (char*)::MapViewOfFile(hMMF, FILE_MAP_WRITE, 0, 0, 0); 

    Write(pBuffer); 

    ::FlushViewOfFile(pBuffer, 100); 

    ::UnmapViewOfFile(pBuffer); 
} 

當我嘗試寫過去分配的大小我已經只分配32個字節的是,我沒有得到任何錯誤的。這是由設計還是這是Windows代碼中的錯誤?但是,如果包含註釋部分,則會發生錯誤,如預期的那樣。

我問這個,因爲我正在考慮使用這個「功能」對我有利。我可以嗎?僅供參考,我有Win XP ver 2002 SP 3,但我懷疑這是「固定」在較新的Windows中,這可能會導致我的代碼IDK失效。任何有用的鏈接解釋一些內部的這將有助於。

感謝

回答

0

虛擬內存管理器具有由頁映射內存,這樣的程度,實際上將四捨五入到最接近的4kB(或任何你的系統頁面大小)。

我不認爲這是記錄是否寫入到映射數據相同的頁面,但超過映射結束,將提交回文件。所以不要依賴那種行爲,它可以在Windows版本之間輕鬆改變。

+0

是的,我確實嘗試超越4kB,現在我明白了。非常感謝。 – mousepad 2011-03-20 18:40:35

2

這並沒有什麼不同,然後寫入超過在堆上分配的緩衝區的末尾。如果您寫入未映射的虛擬內存,操作系統只能敲擊手指。映射是基於頁面的,一頁是4096字節。你必須通過這個頁面才能獲得kaboom。改變你的for循環結束於(4096 + 4)/ 4來重現它。

+0

aaaaah!試圖循環2000次,它確實炸燬了。非常感謝。 – mousepad 2011-03-20 18:39:20