c - 如何调试在调试器中运行的 C 代码?

标签 c gdb initialization lldb

我有以下 C 代码

double ComputeWord (String* word, List* dict, List* words, Matrix* results, String* ret) {
    int i = 0;
    signed long wordIndex = ListFind (words, (void*)word);
    double min = StringSize (word); // Largest possible cost
    int minIndex = 0;
    if (wordIndex == ListEnd (words) ) { 
        ListAppend(words, (void*) word);
        wordIndex = ListSize(words) - 1;
        MatrixExpand (results, 0, ListSize(words));
    }
    for (i = 0; i < ListSize(dict); i++) {
        if (!strcmp (CString(word), CString( (String*)ListElement(dict, i) ) ) ) { min = 0; minIndex = i; break; }
        double current = fromDatabase ((long)MatrixElement(results, i, wordIndex) );
        if (current == 0) {
            printf ("Was not processed\n");
            current = lDist (word, ListElement(dict, i) );
            MatrixSetElement (results, (void*)toDatabase(current), i, wordIndex);
        }
        if (current <= min) { min = current; minIndex = i; }
        printf ("%s to %s - %.1lf\n", word->elementArray, ((String*)ListElement (dict,     i))->elementArray, current);
    }

    String temp;
    StringInit (&temp);
    char temp2[256];

    sprintf (temp2, ",%.1lf", min);

    StringSet (&temp, temp2);

    StringConcatenate(ret, (String*) ListElement (dict, minIndex) );
    StringConcatenate(ret, &temp);

    StringDelete (&temp);
    StringAppend(ret, ' ');
    printf ("matched %s to %s - %.1lf\n", word->elementArray, ((String*)ListElement (dict, minIndex))->elementArray, min);
    return min;
}                                                                  

它的作用是获取一个字典 dict 和一个单词,并尝试使用 demerau-levenshtein 距离 (lDist) 来匹配字典中的单词,然后将结果存储在矩阵中。

发生的情况是,虽然我的算法正确计算距离,但它认为某些单词已经存储,因此它得到不正确的 。 我尝试打开 GDB 来尝试弄清楚发生了什么,但程序在其中运行正确。

我得到的结果是:

creating dictionary
adding aspecto to dict
adding matematica to dict
adding algebra to dict
adding posicao to dict
adding profissao to dict
adding fourier to dict
adding casa to dict
adding calculo to dict
adding dificil to dict
Was not processed
aepscto to aspecto - 3.0
Was not processed
aepscto to matematica - 9.5
Was not processed
aepscto to algebra - 8.5
Was not processed
aepscto to posicao - 5.5
Was not processed
aepscto to profissao - 9.0
Was not processed
aepscto to fourier - 10.5
Was not processed
aepscto to casa - 6.5
Was not processed
aepscto to calculo - 7.0
Was not processed
aepscto to dificil - 9.0
matched aepscto to aspecto - 3.0
Was not processed
caculo to aspecto - 6.5
Was not processed
caculo to matematica - 11.0
Was not processed
caculo to algebra - 8.5
Was not processed
caculo to posicao - 7.0
Was not processed
caculo to profissao - 10.5
Was not processed
caculo to fourier - 9.0
Was not processed
caculo to casa - 5.0
Was not processed
caculo to calculo - 1.0
Was not processed
caculo to dificil - 7.5
matched caculo to calculo - 1.0
Was not processed
matmatica to aspecto - 10.0
Was not processed
matmatica to matematica - 1.0
Was not processed
matmatica to algebra - 9.5
Was not processed
matmatica to posicao - 8.5
Was not processed
matmatica to profissao - 11.5
Was not processed
matmatica to fourier - 11.0
Was not processed
matmatica to casa - 8.0
Was not processed
matmatica to calculo - 10.5
Was not processed
matmatica to dificil - 10.0
matched matmatica to matematica - 1.0
augebra to aspecto - 6.5
augebra to matematica - 11.0
augebra to algebra - 8.5
augebra to posicao - 7.0
augebra to profissao - 10.5
augebra to fourier - 9.0
augebra to casa - 5.0
augebra to calculo - 1.0
augebra to dificil - 7.5
matched augebra to calculo - 1.0

我注意到“augebra”的结果与“caculo”的结果完全相同,这意味着 ListFind 返回“caculo”的索引,但这应该是不可能的,因为我直接使用 strcmp 来实现.

/* Method: StringListComp
 * Parameters:
 * a - First String
 * b - Second String
 * Return value:
 * a == b
 * Description:
 * A specialization of list compare for strings. Compares the strings and returns.
 */

Bool StringListCompare (void* a, void* b) {
    return (Bool)!strcmp ( ( (String*)a)->elementArray, ( (String*)b)->elementArray);
}


/* Method: ListFind                                                                                                                                                                                         
 * Parameters:
 * list - List to search
 * element - Element to find
 * Return value:
 * Returns element if it was found and ListEnd if not.
 * Description:
 * Search list for element.
 */

uintptr_t ListFind (List* list, void* element) {
    uintptr_t i;
    for (i = 0; i < list->size; i++) {
        if ( list->ListCompare(list->elementArray[i], element) ) return i;
    }
    return ListEnd (list);
}

这怎么可能?

编辑: 我想我可能已经发现了这个问题。

当我调用这样的方法时:

    for (i = 0; i < ListSize(&workingStudent); i++) {
        score += ComputeWord (ListElement(&workingStudent, i), &dict, &words, &results, &ret);
        StringDelete ((String*)ListElement (&workingStudent, i);
    }

发生的情况是我正在删除要发送到线路列表的字符串

ListAppend(words, (void*) word);

由于 word 是一个指针,因此字符串被删除,而列表不知道。 这样,String 中的 char* 开始指向可以更改的空闲内存位置。

最佳答案

发生的情况是调试器不允许更改已释放的内存,因此它使删除的单词保持新鲜。但对于现实世界的内存来说,情况并非如此。 解决此问题的方法是删除删除字符串的行并将其添加到代码中:

if (wordIndex == ListEnd (words) ) { 
    ListAppend(words, (void*) word);
    wordIndex = ListSize(words) - 1;
    MatrixExpand (results, 0, ListSize(words));
//==========\/This\/==========//
} else {
    StringDelete (word);
    free (word);
    word = (String*) ListElement (words, wordIndex);
}

因此,当不需要时,单词会被删除,并开始指向已经缓存的单词。 当心调试器及其不必要的数据正确性。

关于c - 如何调试在调试器中运行的 C 代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24060212/

相关文章:

linux - 截断的核心转储有什么用?

C编程gdb报错信息

C++ : Why isn't my call to "std::uninitialized_copy" working?

c - 在 Windows 上将命令通过管道传输到缓冲区

c - 何时使用 fcheck() 或 fcheck_files() 以及为了什么?

go - 如何使用 gdb 或 delve 将断点设置到 go 方法

c - 只读全局数据的线程安全初始化

c++ - 使用 new 表达式创建内置类型

c - 使用一个结构重新散列链式哈希表并调整其大小

c - 使用回溯解决数独错误