използване на libpcre в рекурсивни функции

Някой има ли идеи какво се случва тук? Имам рекурсивна функция, която понякога прави повиквания към pcre, за да съответства на шаблони в низ, който се изгражда. Работи добре, ако няма скоби в шаблона, който се използва за съпоставяне (екранираните скоби също работят добре), но ако използвам шаблон като ([a-z]), valgrind ми дава следната грешка, когато най-дълбоката рекурсивна функция се опита за връщане (използването на модела \([a-z]\) работи добре):

РЕДАКТИРАНЕ: Написах нерекурсивна версия и тя работи добре; възможно ли е libpcre да използва рекурсия, когато има скоби и това по някакъв начин обърква адреса на предишната функция в моята рутина??

==4712== 1 errors in context 1 of 1:
==4712== Jump to the invalid address stated on the next line
==4712==    at 0xFFFFFFFF: ???
==4712==    by 0x40B646: ??? 
==4712==    by 0x40B646: ??? 
==4712==    by 0x40B646: ??? 
==4712==    by 0x40B646: ??? 
==4712==    by 0x40B483: ??? 
==4712==  Address 0xffffffff is not stack'd, malloc'd or (recently) free'd   

linked_list_t *_GetExistingKeysByPattern(linked_list_t *keys,
                                         session_t *session)
{
    char *cKey;
    linked_list_t *existingKeys = ListNew(NULL);
    ListIterSet(keys);
    while (cKey = ListIterNext(keys))
    {   //cKey could be SOFTWARE\\something\\([0-9]\.1) for example
        char keyPath[512];
        keyPath[0] = '\0';
        _GetExistingKeysByPatternHelper(cKey, keyPath, existingKeys, session);
    }
    return existingKeys;
}


void _GetExistingKeysByPatternHelper(char *patternStart,
                                     char *keyPath,
                                     linked_list_t *existing,
                                     session_t *session)
{
    char *ptr, currentKeyPath[512];
    unsigned short endOfPattern = 0;
    char *patternStartCopy = strdup(patternStart);

    if (ptr = strstr(patternStartCopy, "\\\\"))
        *ptr = '\0';
    else
        endOfPattern = 1;

    snprintf(currentKeyPath,
             512,
             "%s%s%s",
             keyPath,
             keyPath[0] == '\0' ? "" : "\\",
             patternStartCopy[0]=='^'?patternStartCopy+1:patternStartCopy);

    if (OpenRegistryEntry(session, currentKeyPath))
    {
        if (!endOfPattern)
            _GetExistingKeysByPatternHelper(ptr + 2,
                                            currentKeyPath,
                                            existing,
                                            session);
        else
            ListInsert(existing, (void *) strdup(currentKeyPath));
    }
    else if (keyPath[0] != '\0')
    {
        // Potential pattern
        if (OpenRegistryEntry(session, keyPath))
        {
            char *subKey;
            unsigned short i = 0;
            while (subKey = EnumerateRegistry(session, i++))
            {
                if (PatternEval(subKey, patternStartCopy, 1))
                {
                    char keyPathCopy[512];
                    snprintf(keyPathCopy,
                             512,
                             "%s\\%s",
                             keyPath,
                             subKey);

                    if (!endOfPattern)
                    {
                        _GetExistingKeysByPatternHelper(ptr + 2,
                                                        keyPathCopy,
                                                        existing,
                                                        session);
                        OpenRegistryEntry(session, keyPath);
                    }
                    else
                        ListInsert(existing, (void *) strdup(keyPathCopy));
                }
                free(subKey);
            }
        }
    }
    free(patternStartCopy);
}

unsigned short PatternEval(char *str, char *pattern, unsigned short carrot)
{
    unsigned short res = 0;
    const char *error;
    int erroroffset, rc, i;
    pcre *re;
    int ovector[100];
    char *tmp;
    if (carrot)
    {
        if (*pattern == '^') pattern++;
        tmp = (char *) malloc (strlen(pattern) + 2);
        sprintf(tmp, "^%s", pattern);
    }
    else
        tmp = pattern;

    if(re = pcre_compile(tmp, PCRE_CASELESS, &error, &erroroffset, 0))
    {
        if ((rc = pcre_exec(re, 0, str, strlen(str), 0, 0, ovector, sizeof(ovector))) >= 0)
            res = 1;
        pcre_free(re);
    }
    else
        printf("pcre_compile failed (offset %d), %s\n",erroroffset,error);

    if (carrot)
        free(tmp);

    return res;
}

person user318747    schedule 08.02.2011    source източник
comment
Публикувайте кода си. Ние не сме екстрасенси.   -  person Adam Rosenfield    schedule 08.02.2011


Отговори (1)


Последният параметър тук е най-малкото грешен:

 pcre_exec(re, 0, str, strlen(str), 0, 0, ovector, sizeof(ovector))

sizeof(ovector) дава размера в байтове, но pcre_exec се нуждае от броя int, така че променете това на

pcre_exec(re, 0, str, strlen(str), 0, 0, ovector, sizeof(ovector)/sizeof(ovector[0]))

В документацията се посочва още

 ovecsize     Number of elements in the vector (a multiple of 3)

Намеква се, че размерът трябва да е кратен на 3, въпреки че тази част е доста неясна.

person nos    schedule 08.02.2011