【问题标题】:Strange integer value causing segmentation fault导致分段错误的奇怪整数值
【发布时间】:2009-05-01 22:57:34
【问题描述】:

我有一个函数 find_nodes(),里面有一个循环:

for (htmlNodePtr current_node=root_node
    ; current_node!=NULL
    ; current_node=current_node->next) 
{
    if (xmlHasProp(current_node,(xmlChar *)"href")) {
        if (xmlHasProp(current_node,(xmlChar *)attribute)) {
            if (strcmp(value,
                (char *)xmlGetProp(current_node,(xmlChar *)attribute))==0) {
                    found_nodes[numb_found]=current_node;
                    numb_found++;
            }
        }
    }

    find_nodes(found_nodes,numb_found,
               current_node->children,mode,attribute,value);

}

我在这个作业中遇到了分段错误:

found_nodes[numb_found]=current_node;

我检查了 numb_found 值,几次迭代都没问题,之后它等于 -1207604106 而不是几个+1

是什么原因造成的?

【问题讨论】:

  • 可能found_nodes是在栈上声明的,它的大小对于numb_found的可能值来说太小了。但我建议您在此处放置一个实际的、可编译的代码,以便我们为您提供帮助。猜谜游戏不好用。
  • 真正有帮助的只是查看 find_nodes() 函数的签名。

标签: c++ integer segmentation-fault


【解决方案1】:

您不知何故超出了数组边界并查看随机数据。

好的,看看这个,我们没有足够的信息,但我观察到这似乎是对 DOM 树的递归搜索。您将 numb_found 作为参数传递,因此当您在递归调用中分配给它时,该值不会在上面更新。最终你会遇到麻烦。

【讨论】:

    【解决方案2】:

    在你的 get_urls 函数中 你声明但没有初始化

    char **url_list;
    

    然后你使用它

    if (tree_is_true(l_list)) {
        url_list[numb_found]=(char *)xmlGetProp(matching_nodes[j],(xmlChar *)"href");
        numb_found++;
    }
    

    -1207604106 是 0xB8056C76 -- 非常适合指针 ;-)

    【讨论】:

    • 好吧 - 我很惭愧错过了这一点(而且我知道有指针没有被释放 - 当我让函数工作时我会得到那个)。它现在工作......有时。对于某些参数,该函数实际上会从测试站点返回正确的 url。对于其他人,它再次在同一个地方崩溃 - 仍然得到这种值:-1208693642
    • 同一个地方——稍后?它在哪个迭代中再次崩溃?也许 256 个匹配节点是不够的 ;-)
    【解决方案3】:

    你踩到了内存。使用-g 编译代码并使用valgrind 运行它,valgrind 会告诉你错误的确切位置。

    【讨论】:

      【解决方案4】:

      从给定的代码中猜测,要么你有一些事情正在踩踏堆栈,要么 numb_found 变得非常大并且溢出。输入一些真实的代码(比如上面所有的类型信息),我们就能告诉你更多。

      我怀疑 found_nodes 是本地堆栈上的一个固定大小的数组,并且您也超出了它的运行范围。

      【讨论】:

        【解决方案5】:

        也许我误解了您的代码,但是由于您传递的是 numb_found 而不是 &numb_found,因此每次从递归返回时,您都将重写找到的节点,这看起来像是对我来说是个错误。

        【讨论】:

        • num_found 被声明为非常量引用,因此调用者的副本会按增量更新。
        【解决方案6】:

        我注意到numb_found 的无效值 (-1207604106) 是 0xB8056C76,这有点像指针值。 可以通过超出数组来解释,尽管您说它没有被超出...

        我建议您验证该数组确实“比需要的大得多”。在将节点添加到数组的行上添加跟踪(使用cerr);至少,让跟踪每次都打印出numb_found 的值。崩溃前您获得的最大值是多少?这实际上与数组大小相比如何?

        【讨论】:

          【解决方案7】:

          这是 valgrind 返回的内容

          ==7464==
          ==7464== Use of uninitialised value of size 4
          ==7464==    at 0x80494EF: find_nodes(_xmlNode**, int&, _xmlNode*, SearchMode, char const*, char const*) (search_engine.cpp:90)
          ==7464==    by 0x8049CF2: get_urls(std::string, ParseTreeNode*, int&) (search_engine.cpp:237)
          ==7464==    by 0x804907B: main (tester.cpp:39)
          ==7464==
          ==7464== Invalid write of size 4
          ==7464==    at 0x80494EF: find_nodes(_xmlNode**, int&, _xmlNode*, SearchMode, char const*, char const*) (search_engine.cpp:90)
          ==7464==    by 0x8049CF2: get_urls(std::string, ParseTreeNode*, int&) (search_engine.cpp:237)
          ==7464==    by 0x804907B: main (tester.cpp:39)
          ==7464==  Address 0xcef11ec0 is not stack'd, malloc'd or (recently) free'd
          ==7464==
          ==7464== Process terminating with default action of signal 11 (SIGSEGV)
          ==7464==  Access not within mapped region at address 0xCEF11EC0
          ==7464==    at 0x80494EF: find_nodes(_xmlNode**, int&, _xmlNode*, SearchMode, char const*, char const*) (search_engine.cpp:90)
          ==7464==    by 0x8049CF2: get_urls(std::string, ParseTreeNode*, int&) (search_engine.cpp:237)
          ==7464==    by 0x804907B: main (tester.cpp:39)
          ==7464==
          ==7464== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 18 from 2)
          ==7464== malloc/free: in use at exit: 73,605 bytes in 3,081 blocks.
          ==7464== malloc/free: 3,666 allocs, 585 frees, 172,154 bytes allocated.
          ==7464== For counts of detected errors, rerun with: -v
          ==7464== searching for pointers to 3,081 not-freed blocks.
          ==7464== checked 329,952 bytes.
          ==7464==
          ==7464== LEAK SUMMARY:
          ==7464==    definitely lost: 186 bytes in 30 blocks.
          ==7464==      possibly lost: 8,324 bytes in 6 blocks.
          ==7464==    still reachable: 65,095 bytes in 3,045 blocks.
          ==7464==         suppressed: 0 bytes in 0 blocks.
          ==7464== Rerun with --leak-check=full to see details of leaked memory.
          

          我得到的最大值是 24,数组有 1024 个元素

          【讨论】:

          • 请编辑您的原始帖子,而不是发布新的“答案”作为更新。
          • 另外,search_engine.cpp:237 和 search_engine.cpp:90 的代码是什么?
          【解决方案8】:

          说真的,您不应该问我们这个问题。您可以更快地执行以下任一操作:

          • 通过调试器运行此程序,单步执行代码并在每条指令后密切关注numb_found;或
          • 在没有调试器的情况下,在每个语句之后放置一个numb_found 的 printf/cout(具有唯一 ID:printf("A:%d\n,numb_found);)。

          这将是准确查看问题原因的最快方法。

          无论如何,您最新的回答/评论表明您将未初始化的值传递给 find_nodes(),并且鉴于其中大多数是指针这一事实,这也会导致您写入无效内存。

          我无法从 valgrind 输出中看出 哪个 参数未初始化,因此在函数顶部放置一个 printf/cout 以打印出所有指针(不是指针的内容)。这应该可以让您查看哪个参数不正确或已损坏。

          【讨论】:

          • 这是未初始化传递的 numb_found,但我现在应该怎么做才能避免它?在第 25 次迭代之前一切正常,然后变量以某种方式被破坏。
          • zacjev,未初始化和损坏是有区别的。首先,您需要将调用 find_nodes() 的函数的完整代码添加到您的问题中,这样我们就可以看到可能导致它的原因,而不是玩猜谜游戏。
          • 我在下面的帖子中添加了这个功能。
          【解决方案9】:

          这是整个函数:

          void find_nodes(htmlNodePtr *found_nodes, int &numb_found, htmlNodePtr root_node, SearchMode mode, const char *attribute, const char *value) {
          
              htmlNodePtr tmp_ptr;
          
              switch (mode) {
          
                  case S_HREF:
                      for (htmlNodePtr current_node=root_node; current_node!=NULL; current_node=current_node->next) {
                          if (xmlHasProp(current_node,(xmlChar *)"href")) {
                              if (xmlHasProp(current_node,(xmlChar *)attribute)) {
                                  if (strcmp(value,(char *)xmlGetProp(current_node,(xmlChar *)attribute))==0) {
                                      found_nodes[numb_found]=current_node;
                                      numb_found++;
                                  }
                              }
                          }
          
                          find_nodes(found_nodes,numb_found,current_node->children,mode,attribute,value);
          
                      }
                      break;
                  case S_KEYWORD:
                      for (htmlNodePtr current_node=root_node; current_node!=NULL; current_node=current_node->next) {
                          if (xmlHasProp(current_node,(xmlChar *)"href")) {
                              if (strcmp(value,(char *)xmlNodeGetContent(current_node))==0) {
                                  found_nodes[numb_found]=current_node;
                                  numb_found++;
                              }
                          }
          
                          find_nodes(found_nodes,numb_found,current_node->children,mode,attribute,value);
                      }
                      break;
                  case S_TAG:
                      for (htmlNodePtr current_node=root_node; current_node!=NULL; current_node=current_node->next) {
                          if (xmlHasProp(current_node,(xmlChar *)attribute)) {
                              if (strcmp(value,(char *)xmlGetProp(current_node,(xmlChar *)attribute))==0) {
                                  tmp_ptr=inner_href_seek(current_node);
                                  if (tmp_ptr==NULL) {
                                      find_nodes(found_nodes,numb_found,current_node->children,mode,attribute,value);
                                      continue;
                                  }
                                  else {
                                      found_nodes[numb_found]=tmp_ptr;
                                      numb_found++;
                                  }
                              }
                          }
          
                          find_nodes(found_nodes,numb_found,current_node->children,mode,attribute,value);
                      }
                      break;
              }
          }
          

          数组是固定的,但比需要的要大得多。我是否以正确的方式传递了 numb_found ?

          === 编辑 ===

          char** get_urls(string url, ParseTreeNode *tree_root, int &numb_found) {
          
              numb_found=0;
              char **url_list;
              htmlDocPtr doc;
              htmlNodePtr root_node;
              string site_content;
          
              if (get_page(url,site_content)<0) {
                  url_list=NULL;
                  return url_list;
              }
          
              // get a DOM
              doc=htmlReadMemory(site_content.data(),site_content.size(),url.data(),NULL,0);
          
              // and the root
              root_node=xmlDocGetRootElement(doc);
          
              if (tree_root==NULL) {
                  url_list=NULL;
                  return url_list;
              }
          
              LeafList *l_list;
              l_list= new LeafList();
          
              l_list->numb_leafs=0;
          
              get_leaf_list(l_list,tree_root);
          
              htmlNodePtr matching_nodes[256];
              int numb_matching_nodes;
          
              htmlNodePtr tmp_nodes[64];
              int numb_tmp;
          
              SearchMode tmp_rule;
          
              for (int i=0;i<l_list->numb_leafs;i++) {
                  if (l_list->leaf_buff[i]->data->rule!=TAG) continue;
                  else {
                      numb_matching_nodes=0;
                      find_nodes(matching_nodes,numb_matching_nodes,root_node,S_TAG,l_list->leaf_buff[i]->data->attribute.data(),l_list->leaf_buff[i]->data->value.data());
          
                      if (numb_matching_nodes==0) continue;
                      else l_list->leaf_buff[i]->state=true;
          
                      for (int j=0;j<numb_matching_nodes;j++) {
                          for (int k=0;k<l_list->numb_leafs;k++) {
                              if (k==i) continue;
                              else {
                                  switch(l_list->leaf_buff[k]->data->rule) {
                                      case HREF:
                                          tmp_rule=S_HREF;
                                          break;
                                      case TAG:
                                          tmp_rule=S_TAG;
                                          break;
                                      case KEYWORD:
                                          tmp_rule=S_KEYWORD;
                                          break;
                                  }
          
                                  find_nodes(tmp_nodes,numb_tmp,matching_nodes[j],tmp_rule,l_list->leaf_buff[k]->data->attribute.data(),l_list->leaf_buff[i]->data->value.data());
          
                                  if (numb_tmp>0) l_list->leaf_buff[k]->state=true;
                                  else l_list->leaf_buff[k]->state=false;
                              }
                          }
          
                          if (tree_is_true(l_list)) {
                              url_list[numb_found]=(char *)xmlGetProp(matching_nodes[j],(xmlChar *)"href");
                              numb_found++;
                          }
                      }
                  }
              }
          
              for (int i=0;i<l_list->numb_leafs;i++) {
                  if (l_list->leaf_buff[i]->data->rule!=HREF) continue;
                  else {
                      numb_matching_nodes=0;
                      find_nodes(matching_nodes,numb_matching_nodes,root_node,S_HREF,l_list->leaf_buff[i]->data->attribute.data(),l_list->leaf_buff[i]->data->value.data());
          
                      if (numb_matching_nodes==0) continue;
                      else l_list->leaf_buff[i]->state=true;
          
                      for (int j=0;j<numb_matching_nodes;j++) {
                          for (int k=0;k<l_list->numb_leafs;k++) {
                              if ((k==i)||(l_list->leaf_buff[k]->data->rule==TAG)) continue;
                              else {
                                  switch(l_list->leaf_buff[k]->data->rule) {
                                      case HREF:
                                          tmp_rule=S_HREF;
                                          break;
                                      case KEYWORD:
                                          tmp_rule=S_KEYWORD;
                                          break;
                                  }
          
                                  find_nodes(tmp_nodes,numb_tmp,matching_nodes[j],tmp_rule,l_list->leaf_buff[k]->data->attribute.data(),l_list->leaf_buff[i]->data->value.data());
          
                                  if (numb_tmp>0) l_list->leaf_buff[k]->state=true;
                                  else l_list->leaf_buff[k]->state=false;
                              }
                          }
          
                          if (tree_is_true(l_list)) {
                              url_list[numb_found]=(char *)xmlGetProp(matching_nodes[j],(xmlChar *)"href");
                              numb_found++;
                          }
                      }
                  }
              }
          
              for (int i=0;i<l_list->numb_leafs;i++) {
                  if (l_list->leaf_buff[i]->data->rule!=KEYWORD) continue;
                  else {
                      numb_matching_nodes=0;
                      find_nodes(matching_nodes,numb_matching_nodes,root_node,S_KEYWORD,l_list->leaf_buff[i]->data->attribute.data(),l_list->leaf_buff[i]->data->value.data());
          
                      if (numb_matching_nodes==0) continue;
                      else {
                          for (int i=0;i<numb_matching_nodes;i++) {
                              url_list[numb_found]=(char *)xmlGetProp(matching_nodes[i],(xmlChar *)"href");
                              numb_found++;
                          }
                      }
                  }
              }
          
              return url_list;
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-04-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多