2017-02-09 76 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