簡體   English   中英

為什么在size_t的情況下拋出bad_alloc()異常

[英]Why bad_alloc() exception thrown in case of size_t

我正在處理下面的代碼,當我執行此代碼時,我得到一個std::bad_alloc異常:

int _tmain(int argc, _TCHAR* argv[])
{
 FILE * pFile;

 size_t state;
 pFile = fopen("C:\\shared.tmp", "rb");
 if (pFile != NULL)
 {
    size_t rt = fread(&state, sizeof(int), 1, pFile);
    char *string = NULL;
    string= new char[state + 1];
    fclose(pFile);
 }
 return 0;
}

這下面的行導致拋出異常:

string = new char[state + 1];

為什么會這樣,我該如何解決這個問題呢?

您正在傳遞未初始化的64位(現代64位系統上的8個字節)變量, state ,並告訴fread讀取sizeof(int) (32位,同一系統上的4個字節)字節將文件存入此變量。

這將覆蓋讀取值的變量的4個字節,但保留其他4個未初始化的。 它覆蓋的4個字節取決於體系結構(在Intel CPU上最不重要,在big-endian配置的ARM上最重要),但結果很可能是垃圾,因為4個字節未初始化並且可能包含任何內容。

在您的情況下,很可能它們是最重要的字節,並且至少包含一個非零位,這意味着您嘗試分配遠遠超過4GB的內存,這是您沒有的。

解決方案是使statestd::uint32_t (因為你顯然希望文件包含4個字節代表無符號整數;不要忘記包含<cstdint> )並傳遞sizeof(std::uint32_t) ,一般情況下確保對於傳遞指針和大小的每個fread和類似的調用,確保指針指向的東西實際上具有您傳遞的大小。 傳遞size_t*sizeof(int)不能滿足64位系統的這些要求,並且由於無法保證C ++基本類型的大小,因此通常不希望將它們用於二進制I / O.

你可以在C ++代碼中改進各種各樣的東西,但是有很多原因,為什么你最終會遇到這種行為:

首先,變量state的類型為size_t ,但是您的代碼嘗試使用fread(&state, sizeof(int), 1, pFile);初始化其值fread(&state, sizeof(int), 1, pFile); 現在,如果sizeof(state) != sizeof(int)那么你有未定義的行為。 如果sizeof(state) < sizeof(int) ,那么fread語句通常會在存儲變量state后覆蓋一些任意內存。 這會導致未定義的行為(例如, state可能具有一些隨機大值,並且分配失敗)。

其次,如果sizeof(state) > sizeof(int) ,則state僅被部分初始化,其實際值取決於初始化(通過fread )和未初始化的位。 因此它的值可能很大,分配可能會失敗。

第三,如果sizeof(state) == sizeof(int)則可能是讀取的值太大,並且分配因為內存不足而失敗。

第四,從文件中讀取的值可能具有一些不同的編碼或字節順序。 例如,如果值寫入到big-endian格式的文件,但fread一個little-endian的CPU上,可能會導致字節被錯誤地交換。 在使用read值之前,您可能需要交換字節。

我建議你改為使用<cstdint> (或<stdint.h> for pre-C ++ 11)中的一些固定寬度整數類型,例如std::uint64_t用於變量state ,使用fread(&state, sizeof(state), 1, pFile);讀取值fread(&state, sizeof(state), 1, pFile); 如果CPU的字節順序與存儲在文件中的值的字節順序不匹配,則為字節交換state

您應該決定您願意分配的最大字符數是多少,如果state大於該值,則應該輸出錯誤。 幾乎可以肯定,它是。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM