Странное целочисленное значение, вызывающее ошибку сегментации - PullRequest
0 голосов
/ 02 мая 2009

Я получил функцию 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, и это нормально для нескольких итераций, и после этого вместо нескольких + 1 оно равно -1207604106

Что может вызвать это?

Ответы [ 9 ]

3 голосов
/ 02 мая 2009

Вы как-то выходите за границы массива и смотрите на случайные данные.

Хорошо, глядя на это, у нас недостаточно информации, но я заметил, что это рекурсивный поиск по дереву DOM. Вы передаете numb_found в качестве аргумента, поэтому, когда вы присваиваете ему в рекурсивном вызове, это значение не будет обновляться выше. В конце концов у вас возникнут проблемы с этим.

2 голосов
/ 02 мая 2009

в вашей функции 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 - идеально подходит для указателя; -)

1 голос
/ 02 мая 2009

Вы растоптали память. Скомпилируйте ваш код с помощью -g и запустите его с помощью valgrind, а valgrind точно скажет вам, где находится ошибка.

0 голосов
/ 02 мая 2009

Серьезно, вы не должны задавать нам этот вопрос. Вам будет гораздо быстрее:

  • запустить это через отладчик, пошагово код и держать часы на numb_found после каждой инструкции; или
  • в отсутствие отладчика, после каждого оператора помещая printf / cout numb_found (с уникальным идентификатором: printf("A:%d\n,numb_found);).

Это будет самый быстрый способ точно определить причину проблемы.

В любом случае ваш последний ответ / комментарий указывает, что вы передаете неинициализированное значение в find_nodes() и, учитывая тот факт, что большинство из них являются указателями, это также приводит к записи в недействительную память.

Я не могу определить из вывода valgrind , какой параметр не инициализирован, поэтому поместите printf / cout вверху функции, чтобы распечатать все указатели ( не содержимое из указателей). Это должно позволить вам увидеть, какой параметр плохой или был поврежден.

0 голосов
/ 02 мая 2009

Это то, что возвратил Вальгринд

==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 элементов

0 голосов
/ 02 мая 2009

Я заметил, что недопустимое значение (-1207604106) для numb_found - 0xB8056C76, которое пахнет как значение указателя. Это может быть объяснено переполнением массива, хотя вы говорите, что он не переполняется ...

Я предлагаю вам убедиться, что массив действительно "намного больше, чем нужно". Добавьте трассировки (используя cerr) в строках, где вы добавляете узел в массив; как минимум, следы распечатывают значение numb_found каждый раз. Какое максимальное значение вы получите до аварии? Как это на самом деле по сравнению с размером массива?

0 голосов
/ 02 мая 2009

Это целая функция:

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;
}
0 голосов
/ 02 мая 2009

Возможно, я неправильно понимаю ваш код, но так как вы передаете numb_found, а не &numb_found, вы просто будете переписывать найденный узел в любом случае каждый раз, когда возвращаетесь из рекурсии, которая выглядит как ошибка для меня.

0 голосов
/ 02 мая 2009

Исходя из данного кода, либо у вас что-то происходит, что топит стек, либо OR numb_found становится очень большим и переполненным. Введите некоторый реальный код (например, информацию о типе для всего вышеперечисленного), и мы сможем рассказать вам больше.

Я бы подозревал, что found_nodes - это массив фиксированного размера в локальном стеке, и что вы также перезапускаете его.

...