2017-05-04 79 views
0

我試圖映射文件到存儲器,和calc其散列:映射LARGE_INTEGER在兩個32位和64位代碼的size_t

// Declaration in header file which I don't control 
void SymCryptSha256(PCBYTE pbData, SIZE_T cbData, PBYTE pbResult); 

// MY code 
HANDLE hFile = ::CreateFile(...); 
HANDLE hMap = ::CreateFileMapping(hFile, nullptr, PAGE_READONLY, 0, 0, nullptr)); 
byte* pMap = ::MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0); 

BYTE[64] hash; 
ULARGE_INTEGER li; 
li.LowPart = ::GetFileSize(file , &li.HighPart); 
// This compiles in 64-bit, but errors in 32-bit: 
// error C4244: 'argument': conversion from 'ULONGLONG' to 'SIZE_T', possible loss of data 
::SymCryptSha256(pMap, li.QuadPart, &hash); 

這是因爲SymCryptSha256的第二個參數是SIZE_T ,在32位編譯中是32位。所需的行爲是:

  • 64位:使用整個尺寸,這是li.QuadPart
  • 32位:在外殼尺寸> 4GB,MapViewOfFile將反正失敗。所以,只需使用li.LowPart即可。

在我看來,我需要這樣做#ifdef s - 有沒有更優雅的方式呢?

+0

@harry:當然你是對的。但是,這是一個簡化的例子 - 我稍後會調用其他API,它需要整個大小爲'SIZE_T'。我編輯了這個問題來反映這一點。 – Jonathan

+0

@Jonathan:哈利是對的,我檢查了我的舊代碼,我也是這樣做的,如果你想要*任何*文件的計算哈希值,就通過0 ... – Malkocoglu

+1

- 你需要準備好文件可以大於4GB。所以你不需要將它映射到內存中(當然,這對於相對較小的文件來說更簡單快捷),而對塊來說則是部分塊。選擇塊大小 - 然後映射塊,計算哈希,取消映射,然後映射下一個塊。大塊大小必須足夠大多數文件使用單個塊,但對於非常大的文件,您將有多個映射/取消映射 – RbMm

回答

0

在一般情況下,使用this trick,你可以做這樣的事情:

if (li.QuadPart > ((ULONGLONG)((size_t)(-1))) too_big(); 
size_t result = (size_t)(li.QuadPart); 

編譯器應該優化第一線成無操作在64位編譯。

(你的具體情況,你可能不需要也無妨;代碼將已經失敗)

注:在評論已經討論過,在這種特殊情況下最好將,如果可能的話,使用散列API,允許你散列數據塊。