在申请大内存的时候,很可能抛出std::bad_alloc异常。
为方便查看,先上解决方案 两种:
- 修改项目属性!项目->属性->配置属性->链接器->系统,找到”启用大地址“选项,选择”是“。
- 将解决方案平台改成64位的。但是可能出现不兼容的问题。
比如说:
- 我最近就需要在跟踪程序里面加载50张4K的图片(3840*2160,BMP格式,23.7MB),总大小超过1GB
- 起初我用OpenCV加载图片,没有std::bad_alloc错误,而是cv::Exception,当时以为是OpenCV自己限制了最多分配多少内存的图片(现在知道我错了,参见我的另一篇博客:http://blog.youkuaiyun.com/a_txpt_001/article/details/40372497 )
- 后来我改用C里面的文件读取操作,按照BMP文件格式,自己读取图片,这里用的是malloc分配空间,最后跟踪结果是错的,但是程序没有报错!!(WTF!)
- 我逐步排查,认为只能是读取图片错误。于是跟进读取图片的函数,单步查错,结果真的发现了猫腻——后面的几张图分配空间失败了!!
// LoadBitmapFile // desc: Returns a pointer to the bitmap image of the bitmap specified // by filename. Also returns the bitmap header information. // No support for 8-bit bitmaps. unsigned char *LoadBitmapFile(char *filename, BITMAPINFOHEADER *bitmapInfoHeader) { FILE *filePtr; // the file pointer BITMAPFILEHEADER bitmapFileHeader; // bitmap file header unsigned char *bitmapImage; // bitmap image data int imageIdx = 0; // image index counter unsigned char tempRGB; // swap variable // open filename in "read binary" mode filePtr = fopen(filename, "rb"); if (filePtr == NULL) return NULL; // read the bitmap file header fread(&bitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, filePtr); // verify that this is a bitmap by checking for the universal bitmap id if (bitmapFileHeader.bfType != BITMAP_ID) { fclose(filePtr); return NULL; } // read the bitmap information header fread(bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, filePtr); // move file pointer to beginning of bitmap data fseek(filePtr, bitmapFileHeader.bfOffBits, SEEK_SET); // allocate enough memory for the bitmap image data bitmapImage = (unsigned char*)malloc(bitmapInfoHeader->biSizeImage); // !!这里会分配失败!! // verify memory allocation if (!bitmapImage) { free(bitmapImage); fclose(filePtr); return NULL; } // read in the bitmap image data fread(bitmapImage, 1, bitmapInfoHeader->biSizeImage, filePtr); // make sure bitmap image data was read if (bitmapImage == NULL) { fclose(filePtr); return NULL; } // swap the R and B values to get RGB since the bitmap color format is in BGR //for (imageIdx = 0; imageIdx < bitmapInfoHeader->biSizeImage; imageIdx+=3) // 不需要!OpenGL 纹理参数 GL_BGR_EXT就可以简单实现 //{ // tempRGB = bitmapImage[imageIdx]; // bitmapImage[imageIdx] = bitmapImage[imageIdx + 2]; // bitmapImage[imageIdx + 2] = tempRGB; //} // close the file and return the bitmap image data fclose(filePtr); return bitmapImage; }
- 我想着,malloc我不熟悉,不如换成我熟悉的new。于是,运行一段时间后,就抛出了std::bad alloc异常。
- 题外话1——这里就看出来了用哪种内存分配方式好了吧!new会弹出异常,malloc屁都不告诉你一声,就让你自个儿找去!!
- 题外话2——当然了,编程高手都有过建议,分配完空间就应该立即检查是否分配成功,所以对老手来说,这不算啥。但是这可害苦了我这只菜鸟%>_<%。所以推荐我这样的菜鸟还是用new来分配空间吧。
- 题外话3——想看new与malloc的区别,可以参考博客:http://blog.youkuaiyun.com/gc315630/article/details/5833554
- 继续,看来两种分配方式都有分配内存的上限啊,这时我也想到原来我采用OpenCV加载图片弹出的cv::Exception 应该也是因为里面用到了malloc或者new,而不是OpenCV自身的原因o(╯□╰)o。
但是,我这个程序挺复杂,还要依赖32位的库函数,将程序改成64位的代价比价大!
其实,还有一种简单的方法就是修改项目属性!
项目->属性->配置属性->链接器->系统,找到”启用大地址“选项,选择”是“。如下图:
从图中可以看见,VS默认应用程序是使用2GB以下的地址的,我程序还有其他的分配空间的地方,所以我粗略测试(加载图片)只能new 1185M的空间。
测试了一下,自己使用new/malloc分配大内存不再出错;使用OpenCV加载几十张图片也不会出错了!
就这样,问题轻松解决!
当申请大量内存导致std::bad_alloc异常时,可以尝试修改项目属性以启用大地址支持,或者将解决方案平台切换为64位。此外,文章探讨了new与malloc在异常处理上的差异,并建议新手使用new进行内存分配。
1万+





