如何调试除非通过gdb运行否则会段错误的代码?

2 投票
2 回答
518 浏览
提问于 2025-04-16 01:02

这段代码是单线程的。

特别提到的是:ahocorasick这个Python扩展模块(可以用easy_install ahocorasick来安装)。

我把问题简化成了一个简单的例子:

import ahocorasick
t = ahocorasick.KeywordTree()
t.add("a")

当我在gdb中运行它时,一切正常,在Python命令行中输入这些指令也没问题。但是,当我尝试正常运行这个脚本时,却出现了段错误(segfault)。

更奇怪的是,导致段错误的那一行(通过核心转储分析找到的)只是一个普通的整数自增操作(可以查看函数体的底部)。

我现在完全卡住了,接下来我该怎么办呢?

int
aho_corasick_addstring(aho_corasick_t *in, unsigned char *string, size_t n)
{
    aho_corasick_t* g = in;
    aho_corasick_state_t *state,*s = NULL;
    int j = 0;

    state = g->zerostate;

    // As long as we have transitions follow them
    while( j != n &&
           (s = aho_corasick_goto_get(state,*(string+j))) != FAIL )
    {
        state = s;
        ++j;
    }

    if ( j == n ) {
        /* dyoo: added so that if a keyword ends up in a prefix
           of another, we still mark that as a match.*/
        aho_corasick_output(s) = j;
        return 0;
    }

    while( j != n )
    {
        // Create new state
        if ( (s = xalloc(sizeof(aho_corasick_state_t))) == NULL )
            return -1;
        s->id = g->newstate++;
        debug(printf("allocating state %d\n", s->id)); /* debug */ 
        s->depth = state->depth + 1;

        /* FIXME: check the error return value of
           aho_corasick_goto_initialize. */
        aho_corasick_goto_initialize(s);

        // Create transition
        aho_corasick_goto_set(state,*(string+j), s);
        debug(printf("%u -> %c -> %u\n",state->id,*(string+j),s->id));
        state = s;
        aho_corasick_output(s) = 0;
        aho_corasick_fail(s) = NULL;
        ++j;                                 // <--- HERE!
    }

    aho_corasick_output(s) = n;

    return 0;
}

2 个回答

0

你有没有试过把那个while循环换成for循环呢?也许在使用++j的时候,你有一些不太明白的地方,如果用更简单的方式来写,就能解决这个问题。

2

还有一些其他工具可以帮助你找到程序中的问题,这些问题不一定会导致程序崩溃。比如说,valgrindelectric fencepurifycoverity,以及类似于lint的工具,可能会对你有帮助。

在某些情况下,你可能需要自己编译一个Python版本才能使用这些工具。此外,对于内存损坏的问题,曾经有(或者现在还有,最近没更新过扩展)一种方法可以让Python直接使用内存分配,而不是使用Python自己管理的内存。

撰写回答