我正在编写一个程序,该程序需要一个包含指向其他包含框架数据的堆的指针的堆。但是我注意到,当我在不再需要堆之后清理堆时,它们仍然很忙。还附有一张内存消耗的图片。
这是RAM使用率上升的图像。
10分钟后MB。
30分钟后达到GB。
此后由于内存访问错误而导致崩溃。
void Trap(vlByte **lpImageData, vlUInt uiCount)
{
if (lpImageData != 0)
{
for (vlUInt i = 0; i < uiCount; i++)
{
if (lpImageData[i] != 0)
{
delete[]lpImageData[i];
}
}
delete[]lpImageData;
}
}
清除函数,在失败和完成时调用。
代码本身
vlByte** lpImageDataRGBA8888 = 0;
lpImageDataRGBA8888 = new vlByte*[uiCount];
memset(lpImageDataRGBA8888, 0, uiCount * sizeof(vlByte *));
vlUInt uiImageSize = vlImageComputeImageSize(uiWidth, uiHeight, 1, 1, IMAGE_FORMAT_RGBA8888);
for (vlUInt i = 0; i < uiCount; i++)
{
lpImageDataRGBA8888[i] = new vlByte[uiImageSize];
if (!vlImageConvertToRGBA8888(vlImageGetData(iType == 1 ? i : 0, iType == 2 ? i : 0, iType == 3 ? i : 0, 0), lpImageDataRGBA8888[i], uiWidth, uiHeight, vlImageGetFormat()))
{
Print("Unable to convert %i frame/face/slice\n", 1 + i);
Trap(lpImageDataRGBA8888, uiCount);
return;
}
}
...
if (!vlImageCreateMultiple(uiWidth, uiHeight, uiFrames, uiFaces, uiSlices, lpImageDataRGBA8888, &CreateOptions))
{
Print("Error Creation Multiple Image\n");
Trap(lpImageDataRGBA8888, uiCount);
return;
}
Trap(lpImageDataRGBA8888, uiCount);
可重复性最低
#include <iostream>
void DLLvlImageCreateMultiple(unsigned int uiCount, unsigned char** lpImageDataRGBA8888)// The dll code
{
unsigned char** lpNewImageDataRGBA8888 = 0;
unsigned int uiImageSize = 256 * 256 * 4; // width * height * byte per pixel
lpNewImageDataRGBA8888 = new unsigned char* [uiCount];
memset(lpNewImageDataRGBA8888, 0, uiCount * sizeof(unsigned char*));
for (unsigned int i = 0; i < uiCount; i++)
{
lpNewImageDataRGBA8888[i] = new unsigned char[uiImageSize];
}
lpImageDataRGBA8888 = lpNewImageDataRGBA8888;
}
void trap(unsigned char** lpImageData, unsigned int uiCount)
{
if (lpImageData != 0)
{
for (unsigned int i = 0; i < uiCount; i++)
{
if (lpImageData[i] != 0)
{
delete[]lpImageData[i];
}
}
delete[]lpImageData;
}
}
void process()
{
unsigned char** lpImageDataRGBA8888 = 0;
unsigned int uiCount = 1; // frames
unsigned int uiImageSize = 1024 * 1024 * 4; // width * height * byte per pixel
lpImageDataRGBA8888 = new unsigned char* [uiCount];
memset(lpImageDataRGBA8888, 0, uiCount * sizeof(unsigned char*));
for (unsigned int i = 0; i < uiCount; i++)
{
lpImageDataRGBA8888[i] = new unsigned char[uiImageSize];
}
DLLvlImageCreateMultiple(uiCount, lpImageDataRGBA8888);
trap(lpImageDataRGBA8888, uiCount);
}
int main()
{
for (unsigned int i = 0; i < 10240; i++) {
std::cout << i << "\n";
process();
}
std::cin;
}
答案 0 :(得分:0)
因此,基本上,堆的工作方式是根据需要分配大的内存块,并为新对象提供请求的空间。通常,PAGE_SIZE为0x1000字节,这是堆管理器可以分配的最小最小块大小。例如,许多结构可能只使用该堆页面的0x40字节,因此,这将浪费大量资源,并导致其他主要问题,无论何时从堆中删除某些内容,都将释放分配的整个页面。当您从堆中释放某些内容时,堆管理器通常会将其标记为此类,以便其他分配可以使用该空间。取决于您的操作系统,释放时可能会选择零内存,但是您也可以自己执行。
包含一个可复制的小样本后,我在评论中提供了其他解释。
您要在
DLLvlImageCreateMultiple
中重新分配内存,并期望将lpImageDataRGBA8888
设置为新分配。来自进程的原始分配被释放,但是第二个则没有。这意味着如果循环成功完成,则发生(256 * 256 * 4 * 10240) = 2,684,354,560 bytes
的内存泄漏。
答案 1 :(得分:0)
DLLvlImageCreateMultiple
中分配的所有内容都是内存泄漏。这就解释了为什么内存使用量一直在单调上升。
行
lpImageDataRGBA8888 = lpNewImageDataRGBA8888;
不会更改调用函数中变量的值。它只是更改函数局部变量的值。
您必须:
返回分配为函数返回值的内存
unsigned char** DLLvlImageCreateMultiple(unsigned int uiCount)
{
...
return lpNewImageDataRGBA8888;
}
或
通过将参数作为参考返回在输出参数中分配的内存。
void DLLvlImageCreateMultiple(unsigned int uiCount,
unsigned char**& lpImageDataRGBA8888)
{
...
}
无论选择哪个路径,都必须确保在更改指针的值之前释放在process
中分配的内存。
void process()
{
unsigned char** lpImageDataRGBA8888 = 0;
unsigned int uiCount = 1; // frames
unsigned int uiImageSize = 1024 * 1024 * 4; // width * height * byte per pixel
lpImageDataRGBA8888 = new unsigned char* [uiCount];
memset(lpImageDataRGBA8888, 0, uiCount * sizeof(unsigned char*));
for (unsigned int i = 0; i < uiCount; i++)
{
lpImageDataRGBA8888[i] = new unsigned char[uiImageSize];
}
trap(lpImageDataRGBA8888, uiCount);
DLLvlImageCreateMultiple(uiCount, lpImageDataRGBA8888);
trap(lpImageDataRGBA8888, uiCount);
}
否则,您将泄漏process
中分配的内存。