为什么在size_t的情况下抛出bad_alloc()异常

Vin*_*mar 3 c++ windows exception

我正在处理下面的代码,当我执行此代码时,我得到一个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;
}
Run Code Online (Sandbox Code Playgroud)

这下面的行导致抛出异常:

string = new char[state + 1];
Run Code Online (Sandbox Code Playgroud)

为什么会这样,我该如何解决这个问题呢?

Seb*_*edl 7

您正在传递未初始化的64位(现代64位系统上的8个字节)变量的地址state,并告诉fread从文件读取sizeof(int)(在同一系统上的32位,4个字节)字节到此变量.

这将覆盖读取值的变量的4个字节,但保留其他4个未初始化的.它覆盖的4个字节取决于体系结构(在Intel CPU上最不重要,在big-endian配置的ARM上最重要),但结果很可能是垃圾,因为4个字节未初始化并且可能包含任何内容.

在您的情况下,很可能它们是最重要的字节,并且至少包含一个非零位,这意味着您尝试分配远远超过4GB的内存,这是您没有的.

解决方案是创建state一个std::uint32_t(因为你显然希望文件包含4个字节表示无符号整数;不要忘记包含<cstdint>)并传递sizeof(std::uint32_t),并且通常确保对于fread传入指针的每个和类似的调用而言一个大小,你确保指针指向的东西实际上具有你传递的大小.传递size_t*sizeof(int)没有履行在64位系统中的这些要求,并且由于C++的基本类型的大小并不保证,你通常不希望在所有使用它们的二进制I/O.