2012-08-30 43 views
2

我在(win32)C++應用程序中發生堆損壞問題。將_heapchk()插入代碼後,我設法縮小了原因。應用程序運行;然而它「偶爾會崩潰」。以下是代碼:在C++中檢測並修復堆損壞

void parse_config(void) { 
    int *regex_d;     // regex data parsed fields(from a line from config_file) 
    vector<string> input_fields;   // filtered data 
    ifstream file(param.topology_file.c_str());// open file for input 
    ifstream reg_file(param.regex_file.c_str()); // open the regex file and read contents(all content is placed on a single line -- no new line characters allowed) 

    if(reg_file.is_open()) 
    { 
     // read regex content into the string regex variable 
     param.regex.assign((istreambuf_iterator<char>(reg_file)), istreambuf_iterator<char>()); 
     reg_file.close(); 
    } 

    split_regex();      
    string buff;      // store contents of input file 
    string::const_iterator start, end; 
    int temp, temp1, temp2; 
    int n_of_fields = 0;   // number of fields found in an input line 
    const size_t l = 10;   // number of digits each data field has 

    for(unsigned i = 0; i < strlen(topology_component); i++) 
    { 
     if(topology_component[i] == ':') 
      n_of_fields++; 
    } 

    input_fields.resize(n_of_fields); 
    regex_d = new int[n_of_fields]; 

    for(vector<string>::iterator iter = input_fields.begin(); iter != input_fields.end(); iter++) 
    { 
     (*iter).reserve(l); 
    } 

     if (file.is_open()) 
     { 
     file.seekg(0, ios::end); 
     buff.reserve(file.tellg()); 
     file.seekg(0, ios::beg); 

     buff.assign((istreambuf_iterator<char>(file)), istreambuf_iterator<char>()); // read contents of file in buff 
     file.close(); 
     boost::regex expression(topology_component); 
     boost::match_results<string::const_iterator> m_res; 
     boost::match_flag_type flags = boost::match_default; 

     start = buff.begin(); 
     end = buff.end(); 

     // searching the buffer for valid entries 
     while(boost::regex_search(start, end, m_res, expression, flags)) 
     { 
      start = m_res[0].second; 
      flags |= boost::match_prev_avail; 
      flags |= boost::match_not_bob; 

      int i = 1; 

      for(vector<string>::iterator iter = input_fields.begin(); iter != input_fields.end(); iter++, i++) 
      { 
       (*iter).erase(); 
       (*iter).append(m_res[i]); 
       sscanf((*iter).c_str(), "%d", &regex_d[i]);  
      } 
         ... 
      } 

     n_of_fields = 0; 
     for(unsigned i = 0; i < strlen(routing_component); i++) 
     { 
     if(routing_component[i] == ':') 
       n_of_fields++; 
     } 

     delete[] regex_d; 
     regex_d = NULL; 
     input_fields.resize(n_of_fields); 
     regex_d = new int[n_of_fields]; 

     for(vector<string>::iterator iter = input_fields.begin(); iter != input_fields.end(); iter++) // allocate memory 
     { 
      iter->reserve(l); 
     } 

     boost::regex expression(routing_component); 
     boost::match_results<string::const_iterator> m_res; 
     boost::match_flag_type flags = boost::match_default; 

     start = buff.begin(); 
     end = buff.end(); 

     // searching the buffer for valid entries 
     // rtable_cur:0 rtable_dst:0 rtable_nxt:0 rtable_vc:0 
     while(boost::regex_search(start, end, m_res, expression, flags)) 
     { 
      start = m_res[0].second; 
      flags |= boost::match_prev_avail; 
      flags |= boost::match_not_bob; 

      // parse one line from config file 
      int i = 1; 

      for(vector<string>::iterator iter = input_fields.begin(); iter != input_fields.end(); iter++, i++) 
      { 
       (*iter).erase(); // <== HEAP CORRUPTION OCCURS HERE 
       (*iter).append(m_res[i]); // <== HEAP CORRUPTION 
       sscanf((*iter).c_str(), "%d", &regex_d[i]); // <== HEAP CORRUPTION 
      } 

      ... 
     } 
     ... 
    } 

當我嘗試重新使用input_fields向量時,堆在整個程序中變爲並保持損壞。 param是一個包含驗證的用戶輸入的容器。 split_regex()方法用於獲取兩個字符串:topology_component和routing_component。兩者都是char *類型。

 void split_regex(void) // regex is of type "topology_component|routing_component" 
    { 
     bool split = false; 
     unsigned i, j = 0; 

     if(topology_component == NULL) 
     { 
      topology_component = (char*)malloc(REGEX_SIZE); 
     } 

     if(routing_component == NULL) 
     { 
      routing_component = (char*)malloc(REGEX_SIZE); 
     } 

     for(i = 0; i < param.regex.size(); i++) 
     { 
     if(split == false) 
     { 
      if(param.regex.at(i) == '|') 
      { 
       split = true; 
       j = 0; 
       continue; 
      } 
      topology_component[i] = param.regex[i]; 
      } 
      else 
      { 
      topology_component[i-1] = '\0'; 
      routing_component[j++] = param.regex[i]; 
      } 
     } 

    routing_component[j] = '\0'; 
    } 
+0

爲什麼不能替換'(* iter).erase(); (* iter).append(m_res [i]);'by'* iter = m_res [i]'?應該避免任何可能的失效問題。 – rasmus

回答

0

該代碼可能正在寫入regex_d數組的末尾。在幾個地方,有代碼指定i = 1;,然後將scanf指定爲regex_d。我懷疑它應該開始搞出來零:

  int i = 1; <== should be 0? 

     for(vector<string>::iterator iter = input_fields.begin(); iter != input_fields.end(); iter++, i++) 
     { 
      <snip> 
      sscanf((*iter).c_str(), "%d", &regex_d[i]);  

此外,它好像是循環應該有一個檢查,以驗證它不會增加過去的regex_d原來的分配大小。

+0

我需要從1開始(我在創建存儲在該regex_d數組中的節點之間的鏈接)。使用0將意味着一個節點創建一個鏈接到它本身,而不是打算 – Sebi

+0

@Sebi:那麼可能regex_d分配應該是'regex_d = new int [n_of_fields + 1]; ' –

+0

這個技巧。我仍然想知道爲什麼解析的第一部分沒有發出任何堆問題的信號。 – Sebi

1

assert(_CrtCheckMemory())對於檢測內存泄漏非常有效。把它放在代碼的不同位置,它會幫助你縮小問題的範圍。您的應用程序必須使用Debug配置進行構建。也可能會減慢執行速度。