C ++内存泄漏在哪里?

时间:2017-02-09 10:50:04

标签: c++ memory-leaks

我对下面附带的代码有疑问。基本上它会产生巨大的内存泄漏,但我无法看到它发生的位置。

enter image description here

代码所做的是接收一个字符串数组,称为打印,包含由','分隔的数字(节点)。 (按desc节点数排序),找到其他兼容的打印件(兼容意味着另一个字符串没有重叠的节点0被排除,因为每个打印包含它),当所有节点都被覆盖时,它会根据加权图计算风险函数。最后,它保留了风险最低的解决方案。

问题在于你在图片中看到的泄漏。我真的无法得到它来自哪里。

以下是代码:

#include "Analyzer.h"

#define INFINITY 999999999

// functions prototypes
bool areFullyCompatible(int *, int, string);
bool contains(int *, int, int);
bool selectionComplete(int , int);
void extractNodes(string , int *, int &, int);
void addNodes(int *, int &, string);

Analyzer::Analyzer(Graph *graph, string *prints, int printsLen) {
    this->graph = graph;
    this->prints = prints;
    this->printsLen = printsLen;
    this->actualResult = new string[graph->nodesNum];
    this->bestResult = new string[graph->nodesNum];
    this->bestReSize = INFINITY;
    this->bestRisk = INFINITY;
    this-> actualSize = -1;
}

void Analyzer::getBestResult(int &size) {

    for (int i = 0; i < bestReSize; i++)
        cout << bestResult[i] << endl;
}

void Analyzer::analyze() {

    // the number of selected paths is at most equal to the number of nodes
    int maxSize = this->graph->nodesNum;
    float totRisk;
    int *actualNodes = new int[maxSize];
    int nodesNum;
    bool newCycle = true;

    for (int i = 0; i < printsLen - 1; i++) {
        for (int j = i + 1; j < printsLen; j++) {

            // initializing the current selection
            if (newCycle) {
                newCycle = false;
                nodesNum = 0;

                extractNodes(prints[i], actualNodes, nodesNum, maxSize);
                this->actualResult[0] = prints[i];
                this->actualSize = 1;
            }

            // adding just fully compatible prints
            if (areFullyCompatible(actualNodes, nodesNum, prints[j])) {
                this->actualResult[actualSize] = prints[j];
                actualSize++;

                addNodes(actualNodes, nodesNum, prints[j]);
            }

            if (selectionComplete(nodesNum, maxSize)) {

                // it means it's no more a possible best solution with the minimum number of paths
                if (actualSize > bestReSize) {
                    break;
                }

                // calculating the risk associated to the current selection of prints
                totRisk = calculateRisk();

                // saving the best result
                if (actualSize <= bestReSize && totRisk < bestRisk) {
                    bestReSize = actualSize;
                    bestRisk = totRisk;
                    for(int k=0;k<actualSize; k++)
                        bestResult[k] = actualResult[k];
                }
            }
        }

        newCycle = true;
    }
}

float Analyzer::calculateRisk() {

    float totRisk = 0;
    int maxSize = graph->nodesNum;
    int *nodes = new int[maxSize];
    int nodesNum = 0;


    for (int i = 0; i < actualSize; i++) {
        extractNodes(this->actualResult[i], nodes, nodesNum, maxSize);

        // now nodes containt all the nodes from the print but 0, so I add it (it's already counted but misses)
        nodes[nodesNum-1] = 0;

        // at this point I use the graph to calculate the risk
        for (int i = 0; i < nodesNum - 1; i++) {
            float add = this->graph->nodes[nodes[i]].edges[nodes[i+1]]->risk;
            totRisk += this->graph->nodes[nodes[i]].edges[nodes[i+1]]->risk;
            //cout << "connecting " << nodes[i] << " to " << nodes[i + 1] << " with risk " << add << endl;
        }
    }

    delete nodes;
    return totRisk;
}

// -------------- HELP FUNCTIONS--------------

bool areFullyCompatible(int *nodes, int nodesNum, string print) {

    char *node;
    char *dup;
    int tmp;
    bool flag = false;

    dup = strdup(print.c_str());
    node = strtok(dup, ",");


    while (node != NULL && !flag)
    {
        tmp = atoi(node);

        if (contains(nodes, nodesNum, tmp))
            flag = true;

        node = strtok(NULL, ",");
    }

    // flag signals whether an element in the print is already contained. If it is, there's no full compatibility

    if (flag)
        return false;

    delete dup;
    delete node;

    return true;
}

// adds the new nodes to the list
void addNodes(int *nodes, int &nodesNum, string print) {

    char *node;
    char *dup;
    int tmp;

    // in this case I must add the new nodes to the list
    dup = strdup(print.c_str());
    node = strtok(dup, ",");

    while (node != NULL)
    {
        tmp = atoi(node);

        if (tmp != 0) {
            nodes[nodesNum] = tmp;
            nodesNum++;
        }

        node = strtok(NULL, ",");
    }

    delete dup;
    delete node;
}

// verifies whether a node is already contained in the nodes list
bool contains(int *nodes, int nodesNum, int node) {
    for (int i = 0; i < nodesNum; i++)
        if (nodes[i] == node)
            return true;
    return false;
}

// verifies if there are no more nodes to be added to the list (0 excluded)
bool selectionComplete(int nodesNum, int maxSize) {
    return nodesNum == (maxSize-1);
}

// extracts nodes from a print add adds them to the nodes list
void extractNodes(string print, int *nodes, int &nodesNum, int maxSize) {

    char *node;
    char *dup;
    int idx = 0;
    int tmp;

    dup = strdup(print.c_str());
    node = strtok(dup, ",");


    while (node != NULL)
    {
        tmp = atoi(node);

        // not adding 0 because every prints contains it
        if (tmp != 0) {
            nodes[idx] = tmp;
            idx++;
        }
        node = strtok(NULL, ",");
    }

    delete dup;
    delete node;

    nodesNum = idx;
}

3 个答案:

答案 0 :(得分:2)

您忘记删除了一些内容,并对您记住的数组使用了错误的删除形式,例如

float Analyzer::calculateRisk() {

    float totRisk = 0;
    int maxSize = graph->nodesNum;
    int *nodes = new int[maxSize];
    //...
    delete [] nodes; //<------- DO THIS not delete nodes

最简单的解决方案是避免使用原始指针而是使用智能指针。或者std::vector,如果你只是想把东西存放到索引的地方。

答案 1 :(得分:1)

您在actualNodes中分配了analyze(),但是您没有在任何地方释放内存:

int *actualNodes = new int[maxSize];

另外,Analyzer::bestResultAnalyzer::actualResultAnalyzer的构造函数中分配,但未在任何地方解除分配。

this->actualResult = new string[graph->nodesNum];
this->bestResult = new string[graph->nodesNum];

如果你必须使用指针,我真的建议使用智能指针,例如使用C ++ 11或更高版本时std::unique_ptr和/或std::shared_ptr,或者使用C ++ 03或更早版本时使用Boost equivalent。否则,使用容器,例如std::vector是首选。

PS:您的代码在分配和解除分配方面也存在很多不匹配。如果使用alloc / calloc / strdup分配内存...则必须使用free释放内存。如果使用operator new分配内存,则必须使用operator delete进行分配。如果使用operator new[]分配内存,则必须使用operator delete[]进行分配。我猜你肯定不应该delete strtok的返回值。

答案 2 :(得分:1)

您有new没有相应的delete

this->actualResult = new string[graph->nodesNum];
this->bestResult = new string[graph->nodesNum];

应使用delete [] ...

删除某些内容