0

内部にループがある関数 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 の値を確認したところ、数回の繰り返しで問題ありませんでした。その後は、few+1 ではなく -1207604106

何が原因でしょうか?

4

9 に答える 9

3

どういうわけか配列の境界を超えており、ランダムなデータを見ています。

これを見ると、十分な情報がありませんが、DOM ツリーを再帰的に検索しているように見えます。引数として渡しnumb_foundているため、再帰呼び出しでそれに割り当てると、その値は上で更新されません。最終的には、それで問題が発生することになります。

于 2009-05-01T23:01:16.733 に答える
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です-ポインタに完全に適合します;-)

于 2009-05-02T15:17:13.473 に答える
1

あなたは記憶を踏みつけました。でコードをコンパイルし-gて実行するとvalgrindvalgrindエラーの正確な場所がわかります。

于 2009-05-01T23:11:14.247 に答える
0

与えられたコードから推測すると、スタックを踏みにじる何かが起こっているか、numb_found が非常に大きくなってオーバーフローしています。実際のコード (上記のすべての型情報など) を入力すると、詳細を知ることができます。

found_nodes がローカルスタック上の固定サイズの配列であり、それをオーバーランしていることも疑わしいです。

于 2009-05-01T23:09:16.590 に答える
0

多分私はあなたのコードを誤解しているかもしれませんが、あなたは を渡しnumb_foundていて を渡していないので&numb_found、再帰から戻るたびに見つかったノードを書き換えるだけです.これは私にはバグのようです.

于 2009-05-01T23:10:03.000 に答える
0

これは関数全体です:

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;
}
于 2009-05-01T23:19:32.463 に答える
0

の無効な値 (-1207604106)numb_foundが 0xB8056C76 であることに気付きました。これはポインター値のような匂いがします。オーバーランしていないと言いますが、それは配列をオーバーランすることで説明できます...

配列が実際に「必要以上に大きい」ことを確認することをお勧めします。cerr配列にノードを追加する行に( を使用して) トレースを追加します。少なくとも、トレースがnumb_found毎回の値を出力するようにします。クラッシュする前に到達した最大値は? それは実際に配列サイズとどのように比較されますか?

于 2009-05-01T23:36:53.763 に答える
0

これは 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 要素があります

于 2009-05-01T23:42:24.560 に答える
0

真剣に、あなたは私たちにこの質問をするべきではありません. 次のいずれかを行う方がはるかに迅速です。

  • これをデバッガーで実行し、コードをシングルステップで実行しnumb_found、各命令の後に監視します。また
  • numb_foundデバッガーがない場合、すべてのステートメントの後に printf/cout を配置します (一意の ID: を使用printf("A:%d\n,numb_found);)。

これは、問題の原因を正確に確認する最も簡単な方法です。

いずれにせよ、最新の回答/コメントは、初期化されていない値を渡していることを示してfind_nodes()おり、それらのほとんどがポインターであるため、無効なメモリへの書き込みも引き起こしています。

どのパラメーターが初期化されていないかをvalgrind 出力から判断できないため、関数の先頭に printf/cout を配置して、すべてのポインター (ポインターの内容ではありません) を出力します。これにより、どのパラメーターが不良であるか破損しているかを確認できます。

于 2009-05-02T01:12:32.503 に答える