2017-05-09 132 views
0

我試圖安裝我的視覺工作室,以便我可以一次性裝入12GB的內存。在Visual Studio中超過4GB的fwrite

我可以看到malloc通過使用監視器跟蹤內存來分配8GB。

但是,fwrite的返回值爲零,輸出文件大小僅爲4GB。

size_t s = fwrite(result, sizeof(unsigned int), 0x80000000, fout); 

我使用的是x64發行模式。

我應該使用其他設置嗎?

+0

你的意思是你在用VS編譯和調試的代碼中?或者你在擴展VS? – Richard

+2

那麼多次調用本地'fwrite'的64位參數實現'_fwrite'函數會出現什麼問題?也許你認爲如果寫入2個4GB的塊,它會工作得更慢? – i486

回答

2

使用最早的C運行時函數處理大數據沒有多少意義,因爲Windows API和C++都有更好的方式來處理更大的數據,例如內存映射文件。對於C++內存映射文件,boost有幾個實現。

如果你真的想用FWRITE,然後嘗試拆分它,如Visual C++的實現FWRITE的一氣呵成不會寫的大陣列:

fwrite是在Windows WriteFile函數的基礎上實現的,只有可以寫一個值得字節的DWORD,並且可以在C:\ Program Files(x86)\ Microsoft Visual Studio 12.0 \ VC \ crt \ src \ fwrite.c中找到它的實現。

/*** 
*size_t fwrite(void *buffer, size_t size, size_t count, FILE *stream) - 
*  write to the specified stream from the specified buffer. 
* 
*Purpose: 
*  Write 'count' items of size 'size' to the specified stream from 
*  the specified buffer. Return when 'count' items have been written 
*  or no more items can be written to the stream. 
* 
*Entry: 
*  buffer - pointer to user's buffer 
*  size - size of the item to write 
*  count - number of items to write 
*  stream - stream to write to 
* 
*Exit: 
*  Returns the number of (whole) items that were written to the stream. 
*  This may be less than 'count' if an error or eof occurred. In this 
*  case, ferror() or feof() should be used to distinguish between the 
*  two conditions. 
* 
*Notes: 
*  fwrite will attempt to buffer the stream (side effect of the _flsbuf 
*  call) if necessary. 
* 
*  No more than 0xFFFE bytes may be written out at a time by a call to 
*  write(). Further, write() does not handle huge buffers. Therefore, 
*  in large data models, the write request is broken down into chunks 
*  that do not violate these considerations. Each of these chunks is 
*  processed much like an fwrite() call in a small data model (by a 
*  call to _nfwrite()). 
*... 

注意通過調用開始不超過0xFFFE字節可以同時寫出的部分寫() - 除了簡單,有沒有優勢了一大段的調用它記憶vs用較小的塊進行幾次呼叫並檢查返回。

+2

我不認爲這是限制發送給'fwrite()'的請求的大小,我把它看作是實現細節,指出這樣一個大的請求將被「分解成塊」。 –

+1

此外,'FFFE'是'WORD',而不是'DWORD'。您正在閱讀Win16時代的評論。 Win32沒有「近陣列」。 – MSalters

+0

@ MSalters微軟沒有更新他們的評論一段時間不是我的錯! –

-1

我不知道爲什麼你會得到零回報值。每the MS documentation for fwrite()

語法

size_t fwrite( 
    const void *buffer, 
    size_t size, 
    size_t count, 
    FILE *stream 
); 

你爲了得到一個4 GB的輸出文件寫入大於零級的項目。到底如何知道返回值爲零?第二,試圖在一行代碼中寫入如此巨量的數據是沒有意義的 - 部分寫入總是可能的,其中任何大小的寫入嘗試都會導致寫入數量少於寫入數量。當你一次寫千兆字節時,部分寫入很可能會發生,所以你必須編寫代碼來處理部分寫操作。性能方面,即使在極高速的磁盤系統上,一旦寫入容量達到兆字節範圍,您將不再看到性能的提升。在消費級商品系統上,一旦寫入請求達到幾千字節,性能就不會提高。第三,如果你不調整你的FILE *對象的緩衝區大小,它可能緩衝在4或8 KB的塊中。這並不是巧合,而是關於大塊大小在大多數磁盤系統上如果有任何性能改進都不會導致太多的巧合。

最後,正如@Andriy Berestovskyy在他的回答中所述,您可能會遇到文件系統限制。查看是否可以使用多個fwrite()調用寫入大於4GB的文件。

+2

「64位Windows將size_t定義爲32位無符號整數類型」。不,它沒有。引用:'#ifdef _WIN64 typedef unsigned __int64 size_t;' – MSalters

+0

「部分寫入總是可能的,任何大小的寫入嘗試都會導致小於寫入的數量。」確實,磁盤可能已滿,這可能是暫時的情況。在實踐中,對於磁盤I/O,「磁盤已滿」不是臨時條件。 – MSalters

+1

「在消費級商品系統上,一旦寫入請求達到幾千字節,性能不會提高。」對於NTFS,這將是65536 KB。 「FILE *」緩衝僅僅是操作系統之前的第一個內部緩衝區,而且你確實有很大的緩衝區。小內部緩衝區可以避免操作系統調用幾個字節,它不會節省物理I/O。 – MSalters