2017-02-09 78 views
-3

我遇到了下面附加代码的问题。本质上它会产生巨大的内存泄漏,但我无法看到它发生的位置。C++内存泄漏,在哪里?

enter image description here

什么代码的作用是接收字符串,称为打印的阵列,包含数字(节点)由分离的“”(由节点的递减数目排序),发现其他兼容打印(兼容装置,其另一个字符串没有重叠节点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; 
} 
+0

你应该使用一个工具来查找泄漏(valgrind,purify,....) – dlavila

回答

1

你分配在analyze()actualNodes但你没有任何地方释放内存:

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[]。我猜你肯定不应该的返回值。

+1

在这种情况下,使用std :: vector 而不是一个智能指针将会更好。 –

+0

@MartinBonner好点,增加我的答案。 – jotik

1

你有new不使用delete [] ...

2

你忘了删除几件事情的地方对应的delete

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

这些应该被删除,用于删除,你必须记住的阵列,例如错误的形式

float Analyzer::calculateRisk() { 

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

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