使用动态内存从转发列表中泄漏内存

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用动态内存从转发列表中泄漏内存相关的知识,希望对你有一定的参考价值。

我正在为我的班级编写一个作业,并且无法完成最后一个要求,即它不会泄漏内存。 Animation.cpp,Frame.cpp和Display.cpp共有3个主要类。动画包含Frame对象的forward_list,Frame包含显示对象的向量。我无法根据分配要求编辑.h文件,这意味着无法更改析构函数。

我认为问题源于为名为“frames”的转发列表中的每个帧使用动态内存分配。由于“frames”和“fileName”是私有类成员,我以后无法使用迭代器来访问它们来调用delete。

我尝试删除每个帧对象的动态内存分配,然后将它们添加到转发列表,但随后帧不打印出来。这是令人困惑的,因为我以前认为前向列表模板管理自己的内存。

简短的版本是我必须构建一个名为deleteFrames()的方法在Animation.cpp类中它仍然会泄漏内存

Animation.cpp

#include <crtdbg.h>
#include <iostream>
#include <string>
#include <vector>
#include <forward_list>
using namespace std;

#include "Display.h"
#include "Frame.h"
#include "Animation.h"
#include "GPUMemoryDisplay.h"
#include "SystemMemoryDisplay.h"

void Animation::InsertFrame() {

    int numDisplays;        //for user input of display number
    vector <Display*>v;     //vector for containing display objects
    int p_x;                //will contain user input for pixel_x
    int p_y;                //will contain user input for pixel_y
    int p_duration;         //will contain user input for duration
    int p_type ;            //will contain display type as int value
    char * p_name;          //temp string to contain user input for name
    string d_name;          //will contain p_name to be passed to display constructor
    string frameName;       //contains user input for the frame name
    string gpu_shader;      //contains gpu name if gpu type is selected
    int q = 0;              //used to count the diplay #

    //begin reading user input
    cout << "Insert a Frame in the Animation
Please enter the Frame filename: ";
    cin >> frameName;
    cout << "Entering the Frame Displays (the sets of dimensions and durations) " << endl;
    cout << "Please enter the number of Displays: ";
    cin >> numDisplays;

    //display creation loop for # of displays entered
    while (numDisplays > 0) {
        cout << "Please enter pixel x-width for Display #" << q << " pixel_x:";
        cin >> p_x;
        cout << "Please enter pixel y-width for Display #" << q << " pixel_y:";
        cin >> p_y;
        cout << "Please enter the duration for this Display: ";
        cin >> p_duration;
        cout << "Please enter the name for this Display: ";
        cin >> d_name;
        cout << "Please enter the type for this display (1 = SystemMemoryDisplay, 2 = GPUMemoryDisplay): ";
        cin >> p_type;
        p_name = new char[d_name.length() + 1]; //allocate for the size of the name entered
        strcpy(p_name, d_name.c_str()); //copy string to char []

        if (p_type == 2) {
            //input for GPU shader
            cout << "Please enter the file name of the associated GPU Shader: ";
            cin >> gpu_shader;
            Display *gpu_p = new GPUMemoryDisplay(p_x, p_y, p_duration, p_name, gpu_shader);
            v.push_back(dynamic_cast <Display*>(gpu_p)); //casting to a display* and pushing onto the vector
            numDisplays--;
            q++;
        }
        else {
            Display *sm_p = new SystemMemoryDisplay(p_x, p_y, p_duration, p_name);
            v.push_back(dynamic_cast <Display*>(sm_p));//casting to a display* and pushing onto the vector
            numDisplays--;
            q++;
        }
        cout << "
";
    }


    Frame *t_frame = new Frame(frameName, v); //new frame holds vector which contains displays


    //check if forward list is empty
    if (frames.empty()) {
        cout << "
This is the first Frame in the list 

";
        frames.push_front(*t_frame);
    }
    else {
        forward_list <Frame>::iterator it;
        int x = 0; // used for size of current forward_list
        //iterate forward list to obtain the size
        for (it = frames.begin(); it != frames.end(); ++it) {
            x++;
        }
        if (x == 1) {
            it = frames.begin();
            frames.insert_after(it, *t_frame);
        }
        else {

            cout << "There are " << x << " Frame(s) in the list
" << "Please specify the position, between 0 and " << x << " to insert after : ";
            cin >> x; //read in where user wants to put the frame

            //iterate to desired position and insert
            forward_list <Frame>::iterator it;
            it = frames.begin();
            while (x != 0 && it != frames.end()) {
                it++;
                x--;
            }
            frames.insert_after(it, *t_frame);
        }
    }
}

void Animation::DeleteFrames() {

    /*MUST DELETE FRAMES HERE*/
    forward_list <Frame>::iterator it; //used to iterate over forward_list

    for (it = frames.begin(); it != frames.end(); it++) {
        Frame tmpF = *it;
        it = frames.erase_after(it);
        it.

    }
    frames.clear();

}

Frame.cpp

#include <crtdbg.h>
#include <iostream>
#include <string>
#include <vector>
#include <forward_list>
using namespace std;

#include "Display.h"
#include "Frame.h"
#include "Animation.h"


Frame::Frame(const Frame & q)
{
    fileName = q.fileName;
    displays = q.displays;
}

Display.cpp

#include <crtdbg.h>
#include <iostream>
#include <string>
#include <vector>
#include <forward_list>
using namespace std;
#include "Display.h"
#include "GPUMemoryDisplay.h"


Display::Display(int x, int y, int d, char* n) :pixel_x(x), pixel_y(y), duration(d), name(n) {
}

Display::Display(const Display& p) {
    //copy values from p
    pixel_x = p.pixel_x;
    pixel_y = p.pixel_y;
    duration = p.duration;
    size_t len = strlen(p.name);
    name = new char[len + 1];
    strcpy(name, p.name);
    //cout << pixel_x << pixel_y << duration << name;

}

Frame.h

#pragma once

class Frame
{
    string fileName;
    vector<Display*> displays; 
public:
    Frame(string s, vector<Display*> d) :fileName(s), displays(d) {}
    Frame(const Frame&);
    ~Frame()
    {
        vector<Display*>::iterator it;
        for (it = displays.begin(); it != displays.end(); it++)
            delete *it;
    }
    friend ostream& operator<<(ostream&, Frame&);
};


//Animation.h
#pragma once

class Animation
{
    string name;
    forward_list<Frame> frames;
public:
    Animation(string s) : name(s) {}
    void InsertFrame();
    void DeleteFrames();
    friend ostream& operator<<(ostream&, Animation&);
};

#pragma once

Display.h

class Display
{
protected:  // accessible to derived classes
    int pixel_x;
    int pixel_y;
    int duration;
    char* name;
public:
    Display(int x, int y, int duration, char* name);
    Display(const Display&);
    virtual ~Display() //makes class abstract, cannot be instantiated, most general class
    {
        if (name)
            delete[]name;
    }
    virtual int BufferSize() = 0; // overridden function Polymorphic function
    friend ostream& operator<<(ostream&, Display&);
};

我正在使用ostream /重载运算符打印出来,但我没有包含它来尝试保持简单。

内存泄漏输出

The thread 0x193c has exited with code 0 (0x0).
The thread 0x2530 has exited with code 0 (0x0).
The thread 0xce8 has exited with code 0 (0x0).
Detected memory leaks!
Dumping objects ->
{236} normal block at 0x010E7650, 4 bytes long.
 Data: < w  > D0 77 0E 01 
{235} normal block at 0x010ED928, 8 bytes long.
 Data: < ;      > 8C 3B 0E 01 00 00 00 00 
{234} normal block at 0x010ED9D0, 8 bytes long.
 Data: <p;      > 70 3B 0E 01 00 00 00 00 
{230} normal block at 0x010E3B70, 44 bytes long.
 Data: <    Frame1      > D0 D9 0E 01 46 72 61 6D 65 31 00 CD CD CD CD CD 
Object dump complete.
The program '[4292] Assignment3.exe' has exited with code 0 (0x0).
答案
void Animation::DeleteFrames() {
if (!frames.empty)
    frames.clear;

}

短版工作正常

以上是关于使用动态内存从转发列表中泄漏内存的主要内容,如果未能解决你的问题,请参考以下文章

在片段中保存活动实例:是否会导致内存泄漏?

FragmentStatePagerAdapter 内存泄漏(带有 viewpager 的嵌套片段)

避免android片段中内存泄漏的最佳方法是啥

COM 互操作中动态代码的内存泄漏

IOS性能调优系列:使用Instruments动态分析内存泄漏

IOS性能调优系列:使用Instruments动态分析内存泄漏