在C ++中检测和修复堆损坏

时间:2012-08-30 22:18:40

标签: c++ visual-studio heap corruption

我在(win32)C ++应用程序中遇到堆损坏问题。将_heapchk()插入代码后,我设法缩小了原因。该应用程序运行;然而它“时不时地”崩溃。这是代码:

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';
   }

2 个答案:

答案 0 :(得分:1)

断言(_CrtCheckMemory())非常适合检测内存泄漏。将它放在代码的各个位置,它将帮助您缩小问题范围。您的应用程序必须使用Debug配置构建。它也可能减慢执行速度。

答案 1 :(得分: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的原始分配大小。