【问题标题】:Segmentation fault while iterating over linked list in C迭代C中的链表时出现分段错误
【发布时间】:2021-09-03 13:33:57
【问题描述】:

我是在 C 中使用链表实现无向图结构的初学者(存储在图中每个节点的数组中)。

这些是我在标题中声明的结构:

    typedef int NodeType;
    typedef int Weight;
    
    typedef struct Edge{
        NodeType destination;
        NodeType node;
        Weight weight;
        struct Edge *next;
    }Edge;
    
    typedef struct Graph {
        int noNodes;
        int noEdges;
        int time;
        Edge edges [MAX_NODES];
    }Graph;

主文件构建图形并尝试按如下方式打印它:

int nextInt(void) {
    char str[11];
    char c;
    for (int i; i < 10;){
        c = fgetc(stdin);
        if (c == '1' || c == '2' || c == '3' || c == '4' || c == '5' ||
            c == '6' || c == '7' || c == '8' || c == '9' || c == '0' ){
            str[i] = c;
            i += 1;
        } else {
            if (i > 0 || c == EOF){
                str[i] = '\0';
                i = 0;
                break;
            }
        }
    }
    int out = atoi(str);
    return out;
}
   Graph initGraph(){
    int noNodes = nextInt();
    int noEdges = nextInt();
    struct Graph graph = {noNodes, noEdges, 0};
    for(int i = 0; i < noNodes; i++){
        Edge newEdge = {-1, i, -1, NULL};
        graph.edges[i] = newEdge;
    }
    for(int i = 0; i<noEdges; i++){
        int a = nextInt();
        int b = nextInt();
        int w = nextInt();
        Edge ea = {b, a, w};
        Edge eb = {a, b, w};
        Edge previous = graph.edges[a];
        graph.edges[a].next = &previous;
        graph.edges[a] = ea;
        previous = graph.edges[b];
        graph.edges[b].next = &previous;
        graph.edges[b] = eb;
    }
    return graph;
}

 bool edgeInArray(Edge edge, Edge edgeArray [], int size){
        for(int i = 0; i < size; i++){
            if((edge.destination == edgeArray[i].destination &&
               edge.node == edgeArray[i].node) ||
               (edge.node == edgeArray[i].destination &&
                edge.destination == edgeArray[i].node)) return true;
        } return false;
    }
    
void printGraph(Graph *graph){
    Edge *temp [graph->noEdges * 2];
    printf("%d %d\n", graph->noNodes, graph->noEdges);
    for(int i = 0; i < graph->noNodes; i++){
        printf("node %d first destination: %d\nnode %d first next destination: %d\n", i, graph->edges[i].destination, i, graph->edges[i].next->destination);
        for (Edge *k = &graph->edges[i];k->next!=NULL;k=k->next){
            printf("a");
            printf("%d", k->destination);
            bool a = edgeInArray(*k, *temp, graph->noEdges * 2);
            if(!a){
                printf("entrou");
            }
        }
    }
}

int main() {
    Graph graph = initGraph();
    printGraph(&graph);
    return 0;
}

我已经测试了 initGraph() 函数,并且我(几乎)确定我在那里没有问题,但是当我尝试运行 printGraph() 函数时,代码甚至没有到达在 Edge 上迭代的循环链表。当我添加 printf 来测试访问当前边缘和下一个边缘时,我在输出中遇到了分段错误。我不知道应该如何处理下一个节点,因为每次我尝试这样做时都会遇到分段错误。

【问题讨论】:

  • 请显示initGraph 和任何其他缺失的代码。也就是说,请提供complete minimal reproducible example。此外,在调试器中运行您的程序。至少,这将为您提供触发 seg 错误的确切代码行,您应该将其添加到帖子中。
  • @kaylum 我刚刚添加了initGraph。你会推荐什么调试器?
  • 这个temp 是一个未初始化的指针数组。然后你以某种方式将它的第一个元素传递给edgeInArray,然后取消引用它以与某些东西进行比较......看起来不像会起作用的东西,除非我错过了什么。
  • graph.edges[a].next = &amp;previous; 分配一个指向本地对象的指针。有强烈的气味。
  • @MikeCAT 你会建议什么?

标签: c pointers data-structures linked-list


【解决方案1】:

对不起,这只是一个不符合评论格式的评论。在您的表达式字段中,edges 中的“next”在下一个语句中立即被覆盖为 NULL:

      Edge previous = graph.edges[a];
      graph.edges[a].next = &previous;
      graph.edges[a] = ea; // <<<

您应该将最后两个语句替换为 a 和以下 b

您还忘记提供您的nextInt() 函数。你能保证它的值在0..MAX_NODES-1的范围内吗?你能保证数组元素已经初始化了吗?

【讨论】:

  • 我添加了nextInt() 函数。已经预计用户输入不大于MAX_NODES。是的,我认为应该初始化数组元素,因为在initGraph() 中创建了一个 Null Edge 元素并将其分配给每个数组索引
  • 因此,它可以返回一个非常任意的数字,您甚至不检查范围或重复。您可以轻松破坏内存或覆盖旧值。你按照我的建议交换语句了吗?
猜你喜欢
  • 2020-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-07
  • 2018-10-29
  • 2015-05-18
  • 2017-11-24
  • 1970-01-01
相关资源
最近更新 更多