此处的size是一个variable,即,变量,下面将出错的代码贴出
// 将文件读入内存,返回内存指针与文件的大小 bool GetFileToMemory( const char *pFilename, char* &pContent, int &size) { FILE *pFile = NULL; if ((pFile = fopen(pFilename, "r")) == NULL) { printf("打开文件%s失败! \r\n", pFilename); return false; } // 获取文件大小 fseek(pFile, 0, SEEK_END); fgetpos(pFile, (fpos_t*)&size); // 获取文件内容 if (pContent == NULL) { pContent = new char[size]; } memset(pContent, 0, size); fread(pContent, 1, size, pFile); fclose(pFile); return true; } void test4() { const char *pFilename = "temp.txt"; char *pContent = NULL; int size; GetFileToMemory(pFilename, pContent, size); if (pContent != NULL) { delete [] pContent; } } void main() { test4(); system("pause"); }
在网上查了一下关于这个错误,大概的解释就是:变量的栈信息被改变了,这里有一个参考文章说的蛮好的:
比如说我这里的size这个变量,它的大小在32位机上面是4个字节,而每个变量的前面和后面是有几个字节存放的是这个变量的信息,如前面一个字节和后面一个字节存放的是这个变量的信息(具体是什么信息我不记得了,就记得变量在运行时实际中所占的字节不是你认为的那么多,而是包含了这个变量的相关信息,哪位大侠知道的话,麻烦给我一下连接,我也好学习一下这方面的内容<^^>),这样一来,如果你一不小心改变这个部分的信息,就有可能引起程序的崩溃,就像我上面的截图那样
下面说一下,我贴的这段代码错误所在,我想看完上面的那个简要的分析,应该就知道是哪里出问题了吧,没错,就是size这个变量,在test4()函数中,它被定义成了int类型,在32位机上面它占有4个字节,以“引用”的方式传入到GetFileToMemory()这个函数中,而在这个函数中有一个这样的调用
fgetpos(pFile, (fpos_t*)&size);
即,把文件的大小写到size中,fgetpos()要求传入是一个fpos_t*的类型,而size是int类型,此处将int取了地址,并强制将地址转换为fpos_t这个类型,看一下fpos_t这个类型的原型:typedef __int64 fpos_t; 看到了吧,它是__int64类型的,即,它在32位机上面占有8个字节!!! OK了,把四个字节的地址传给操作8个字节的函数,它就操作了另外的四个字节,这样,原来size的"变量信息栈"所占有的字节就被破坏了,所以在出test()这个函数的时候就出现了上面的那个对话框!
只要做一下修改,像这样:
fpos_t outSize = 0;
fgetpos(pFile, (fpos_t*)&outSize);
size = (int)outSize;
fgetpos(pFile, (fpos_t*)&outSize);
size = (int)outSize;
这样就OK了,在这个地方建议存放文件大小的变量就使用fpos_t这个类型来定义,这样就不会出现上面的那个麻烦了,Win32 API 里面也有说到,早期获取文件大小的API是会有错误的,因为提取大文件的时候,一个DWORD是不够存放文件的大小的(sizeof(DWORD) == sizeof(int) 在32位机上面),WIN32 API也是使用两个DWORD来存放文件的大小的,所以......,你懂的......
关于这个错误,具体代码要做具体分析,我的分析就到这里!