代码不起作用。但是调试的时候呢

Code doesn't work. But does when debugging

我在这里需要一些帮助,但我无法通过搜索找到任何相关内容。

所以我正在编写一个 C 程序,但发生了一些奇怪的事情。当我 运行 它正常时我的程序崩溃了,但是当我调试它时,它工作正常。我不明白发生了什么。

这是一项作业,将于周三到期,所以我有点害怕。

(我正在使用 CodeBlocks IDE,如果有帮助的话。)

编辑: 很抱歉没有从一开始就发布这个,我认为问题可能是我错误地使用了调试器或者不得不更改调试器设置(如果可能的话)。 这是接缝导致问题的功能:

double **makeMatrix(struct graph *head, char **nodes)
{
    double **tmpMatrix=NULL;
    int i=0, j=0;
    struct graph *tmp=NULL;


    if(nodes==NULL || head==NULL)
        return NULL;

    for(i=0; nodes[i] != NULL; i++);

    tmpMatrix=calloc(i+1, sizeof(double*));

    if(NULL==tmpMatrix)
    {
        printf("No Memory!");
        return NULL;
    }

    for(j=0; j<i; j++)
    {
        tmpMatrix[j]=calloc(i+1, sizeof(double*));

        if(NULL==tmpMatrix[j])
        {
            printf("No Memory!");
            return NULL;
        }
        tmpMatrix[j][i] = -INF;
    }

    for(i=0; tmpMatrix[i] != NULL; i++)
    {
        for(j=0; tmpMatrix[i][j] != -INF; j++)
        {
            tmpMatrix[i][j] = INF;
        }
    }

    for(tmp=head; tmp->fromNode >=0; tmp= tmp->next)
    {
        tmpMatrix[tmp->fromNode][tmp->toNode] = tmp->length;
        printf("%f\n", tmpMatrix[tmp->fromNode][tmp->toNode] );
    }

    return tmpMatrix;
}

作业是关于编写一个程序,该程序能够读取节点和图形以计算最短路径。哪里给出了Dijkstra算法来解决这个问题。这就是为什么我们必须创建一个矩阵来存储边的长度。

此外,我正在使用调试器逐步执行它。

根据您未显示的所有代码和输入,我发现了一些问题或潜在问题:

  1. 行:

    tmpMatrix[j]=calloc(i+1, sizeof(double*));
    

    应该是:

    tmpMatrix[j]=calloc(i+1, sizeof(double));
    

    如果sizeof(double*) == 8你可能碰巧没问题,但最好是真的正确

  2. 在第一个 for 循环中,您似乎在计算 nodes 数组的大小。我不明白在这种情况下节点的使用,因为它没有在函数的其他地方使用。更好的函数签名是传递所需数组的大小。确保 nodes 已正确 NULL 终止,否则你会 运行 出问题。我还会添加另一个变量以使数组大小明确,因为您稍后会重用 i,例如:

    int arraySize = 0;
    ...
    for (i = 0; nodes[i] != NULL; ++i);
    arraySize = i;
    tmpMatrix = calloc(arraySize + 1, sizeof(double*));
    
  3. 为了将 tmpMatrix 的值设置为 INF 最好使用显式数组索引,例如:

    for (i = 0; i < arraySize; ++i)
    {
        for (j = 0; j < arraySize; ++j)
        {
            tmpMatrix[i][j] = INF;
        }
    }
    

    这使您在做什么时更加清晰并且不易出错。

  4. 您应该在最后一个循环中明确检查 NULL 指针:

    for (tmp = head; tmp->fromNode >= 0; tmp = tmp->next)
    

    如果链接列表设置不正确,那么 tmp 可能会变成 NULL 并且您将取消引用它,从而导致未定义的行为。只需在循环中添加一个检查,如:

    for (tmp = head; tmp != NULL && tmp->fromNode >= 0; tmp = tmp->next)
    
  5. 您应该在最后一个循环中检查 tmpMatrix 的有效数组索引:

    tmpMatrix[tmp->fromNode][tmp->toNode] = tmp->length;
    

    如果 tmp->fromNodetmp->toNode 是无效的数组索引,您将 overflow/underflow 数组并导致 UB。即使您 "know" 这些值应该是正确的,添加检查以防万一也更安全:

    if (tmp->fromNode >= 0 && tmp->fromNode < arraySize &&
        tmp->toNode   >= 0 && tmp->toNode   < arraySize) 
    {
       ...
    }
    

其中很多点都属于 "defensive programming" 类别。是的,nodeshead 应该以 NULL 终止并具有正确的索引,但也许某处存在另一个错误但它们不是,或者收到了无效输入,或者杂散宇宙射线在记忆细胞。通过更仔细地检查您的输入,您可以防止 UB 发生并像您所经历的那样随机崩溃。