【问题标题】:using libpcre in recursive functions在递归函数中使用 libpcre
【发布时间】:2011-06-23 15:09:37
【问题描述】:

有人对这里发生的事情有任何想法吗?我有一个递归函数,它有时会调用 pcre 以匹配正在构建的字符串中的模式。如果用于匹配的模式中没有括号,它可以正常工作(转义括号也可以正常工作),但是如果我使用诸如 ([az]) 之类的模式,则当最深的递归函数尝试时,valgrind 会给我以下错误返回(使用模式 \([az]\) 工作正常):

编辑:我写了一个非递归版本,效果很好;当存在括号时,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;
}

【问题讨论】:

  • 发布您的代码。我们不是通灵者。

标签: c recursion pcre valgrind


【解决方案1】:

这里的最后一个参数至少是错误的:

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

sizeof(ovector) 以字节为单位给出大小,但 pcre_exec 需要整数的数量,因此将其更改为

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 的倍数,虽然这部分不太清楚。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-12
    • 2019-05-30
    • 2019-04-02
    • 2018-10-03
    • 2021-12-12
    相关资源
    最近更新 更多