gpt4 book ai didi

c++ - 我的内存没有被释放

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:27:46 25 4
gpt4 key购买 nike

我有一个相当大的程序,通常运行得非常好,但运行时占用大量内存。这是一种收集大量数据的机器学习方法,因此通常没问题,但即使收集了所有数据,内存也会增长得非常快,所以我使用 valgrind massif 来找出问题所在。 massif 堆树的顶部如下所示:

99.52% (60,066,179B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc.
->43.50% (26,256,000B) 0x439785: Image::Image(SDL_Surface*) (Image.cpp:95)
| ->43.50% (26,256,000B) 0x437277: EncodedFeature::forwardPass() (EncodedFeature.cpp:65)
....

所以我想,嗯,也许构建的图像不是免费的,但不是:

void EncodedFeature::forwardPass()
{
// Get image:
Image* img = new Image(screen);

// Preprocess:
if(preprocessor)
preprocessor->process(img);

// Do forward pass:
encoder->encode(img, features);

delete img;
}

所以对于图像构造函数:

Image::Image(SDL_Surface* surface)
{
this->width = surface->w;
this->height = surface->h;
pixels = new int*[width];
for(int i = 0; i < width; i++)
pixels[i] = new int[height];

for(int x = 0; x < surface->w; x++)
for(int y = 0; y < surface->h; y++)
pixels[x][y] = getPixelFromSDLSurface(surface, x, y);
}

只是分配一个像素数组,稍后在析构函数中释放:

Image::~Image()
{
if(!pixels)
return;

for(int x = 0 ; x < width; x++)
delete[] pixels[x];

delete[] pixels;
}

所以最后一个罪魁祸首:

Uint32 Image::getPixelFromSDLSurface(SDL_Surface *surface, int x, int y)
{
if(!surface)
return 0;

// Got this method from http://www.libsdl.org/cgi/docwiki.fcg/Pixel_Access
int bpp = surface->format->BytesPerPixel;
/* Here p is the address to the pixel we want to retrieve */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

switch(bpp) {
case 1:
return *p;
break;

case 2:
return *(Uint16 *)p;
break;

case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
return p[0] << 16 | p[1] << 8 | p[2];
else
return p[0] | p[1] << 8 | p[2] << 16;
break;

case 4:
return *(Uint32 *)p;
break;

default:
return 0; /* shouldn't happen, but avoids warnings */
}
}

正如评论中提到的,我从 SDL wiki 那里得到了那个,所以我希望那里没有任何泄漏。在我的例子中,bpp 实际上总是 1,所以它只返回地址 p 处的 int,这对我来说听起来不漏。

我已经无计可施了。谁能想到内存去了哪里?我的意思是,massif 专门指向 Image 构造函数,但我看不出那里有什么问题...

非常感谢您查看我的问题!

最大


回复您的评论:

你是对的,我不需要 img 作为指针。我来自 Java 背景,所以我只希望一切都是指针 :) 更改它但没有帮助。

第 95 行在构造函数的第一个 for 循环内:pixels[i] = new int[height];

在其中一个预处理器中,我确实调整了图像的大小,但我这样做是调用我的重置函数,它应该确保删除旧数组:

void Image::reset(int width, int height)
{
if(pixels)
{
// Delete old image:
for(int x = 0 ; x < width; x++)
delete[] pixels[x];

delete[] pixels;
}

this->width = width;
this->height = height;
pixels = new int*[width];
for(int i = 0; i < width; i++)
pixels[i] = new int[height];
}

之后我重新填充像素值...

任何地方都不会抛出异常。

您建议我在哪里使用智能指针?

谢谢大家的回答!

最佳答案

我认为您在图像类中没有正确表示像素。我认为您可以使用正确无符号类型的简单一维 vector(uint32_t?)。

(在标题中):

class Image {
protected:
std::vector<uint32_t> pixels;
...
};

(在实现文件中)

size_t Image::offset(unsigned x, unsigned y) {
return (y * width) + x;
}

Image::Image(const SDL_Surface* surface)
{
width = surface->w;
height = surface->h;
pixels.reserve(width * height);
for(unsigned x = 0; x < width; x++)
for(unsigned y = 0; y < height; y++)
pixels[offset(x, y)] = getPixelFromSDLSurface(surface, x, y);
}

你的析构函数将完全是空的,因为它无事可做:

Image::~Image() {
}

请注意,对于任何给定的 x/y 对,您需要使用 offset() 方法为 vector 获取正确的索引。

关于c++ - 我的内存没有被释放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18254186/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com