繁体   English   中英

倒带文件指针时出现分段错误

[英]segmentation fault when rewinding my file pointer

当我的文件指针命中它的第二次倒带时,它会导致段错误。 我不知道为什么。 我将在顶部包含有问题的主要内容及其下方的所有代码。

int main(void){
    // creating the file pointer
    FILE *fptr = fopen("input-machine-problem-1.txt", "r");
    if (fptr == NULL) {
        printf("Error! opening file");
        return 0;
    }

    int edges;
    int vertices;
    int* edgesPtr = &edges;
    int* verticesPtr = &vertices;
    getNumberOfVerticesAndEdges(fptr, verticesPtr, edgesPtr);

    LinkedList arrayOfLinkedLists[vertices];

    int x, y;
    for(int i = 0; i < vertices; i++){ 
        if(fptr == NULL){
            return 0;
        }
        rewind(fptr);
        for(int j = 0; j < edges; j++){
            
            printf("%d: ", j);
            fscanf (fptr, "%d %d", &x, &y);    
            printf ("%d %d ", x, y);
            if(i == x){
                push(arrayOfLinkedLists[i], y);
            } else if(i == y){
                push(arrayOfLinkedLists[i], x);
            }
            printf("**\n");
        }
    }

    // printAdjacencyLists(arrayOfLinkedLists, vertices);
    fclose (fptr); 
}

如果您想复制和粘贴整个文件:

#include <stdio.h>
#include <stdlib.h>

typedef struct node{
    int vertexNumber;
    struct node *next;
} Node;

typedef struct linkedList{
    Node* head;
    int size;
} LinkedList;

void getNumberOfVerticesAndEdges(FILE* fp, int* vertices, int* edges);
void push(LinkedList linkedList, int vertex);
Node* createNode(int vertexNumber);
void printAdjacencyLists(LinkedList* arrayOfLinkedLists, int vertices);

int main(void){
    // creating the file pointer
    FILE *fptr = fopen("input-machine-problem-1.txt", "r");
    if (fptr == NULL) {
        printf("Error! opening file");
        return 0;
    }

    int edges;
    int vertices;
    int* edgesPtr = &edges;
    int* verticesPtr = &vertices;
    getNumberOfVerticesAndEdges(fptr, verticesPtr, edgesPtr);

    LinkedList arrayOfLinkedLists[vertices];

    int x, y;
    for(int i = 0; i < vertices; i++){ 
        if(fptr == NULL){
            return 0;
        }
        rewind(fptr);
        for(int j = 0; j < edges; j++){
            
            printf("%d: ", j);
            fscanf (fptr, "%d %d", &x, &y);    
            printf ("%d %d ", x, y);
            if(i == x){
                push(arrayOfLinkedLists[i], y);
            } else if(i == y){
                push(arrayOfLinkedLists[i], x);
            }
            printf("**\n");
        }
    }

    // printAdjacencyLists(arrayOfLinkedLists, vertices);
    fclose (fptr); 
}

void push(LinkedList linkedList, int vertex){
    Node* newNode = createNode(vertex);

    Node* cur = linkedList.head;
    Node* prev = cur;
    if(cur == NULL){
        linkedList.head = newNode;
        return;
    }
    while(newNode->vertexNumber > cur->vertexNumber){
        prev = cur;
        cur = cur->next;
    }
    newNode->next = cur;
    prev->next = newNode;


}

Node* createNode(int vertexNumber){
    Node* newNode = malloc(sizeof(Node));
    if(!newNode){
        return NULL;
    }
    newNode->vertexNumber = vertexNumber;
    newNode->next = NULL;
    return newNode;
}

void getNumberOfVerticesAndEdges(FILE* fp, int* vertices, int* edges){
    if (fp == NULL) {
        printf("Error! opening file");
        return;
    } 

    *vertices = 0;
    *edges = 0;
    while(1){
        int x, y;

        fscanf(fp, "%d %d^\n", &x, &y);

        if(x > *vertices){
            *vertices = x;
        } if (y > *vertices){
            *vertices = y;
        }

        *edges = (*edges) + 1;

        if(feof(fp)) { 
            return;
        }
    }
}

void printAdjacencyLists(LinkedList* arrayOfLinkedLists, int vertices){
    for(int i = 0; i < vertices; i++){
        printf("\n%d:  ", i);
        if(arrayOfLinkedLists[i].head == NULL){
            return;
        }
        Node* cur = arrayOfLinkedLists[i].head;
        while(cur != NULL){
            printf("%d --> ", cur->vertexNumber);
            cur = cur->next;
        }
    }
}

您需要通过fscanf()的返回来控制读取循环,例如

void getNumberOfVerticesAndEdges(FILE* fp, int* vertices, int* edges)
{
    int x, y;
    
    if (fp == NULL) {
        printf("Error! opening file");
        return;
    } 

    *vertices = 0;
    *edges = 0;
    while (fscanf(fp, "%d %d", &x, &y) == 2) {
        if(x > *vertices){
            *vertices = x;
        } if (y > *vertices){
            *vertices = y;
        }

        *edges = (*edges) + 1;
    }
}

注意:格式字符串中不需要^\\n

这确保您仅在xy的值持有有效值时才使用它们。 正如您所写的, xy或两者都可能导致转换失败(匹配输入失败),并且您仍然使用这些值进行比较,并根据结果将值分配给*verticies而不保证xy是有效的。

此外,正如你所写的, *edges = (*edges) + 1; fscanf()失败之后和检查导致edges为一的边太多的流状态之前执行。

除非您检查 return ,否则您无法正确使用任何输入函数。 如果您还有其他问题,请告诉我。 您的代码可能有其他问题,但一旦读取失败——这可能是您的第一个主要问题。

下一段故障

您的下一个 SegFault 位于push()

while(newNode->vertexNumber > cur->vertexNumber){
    prev = cur;
    cur = cur->next;
}

在取消引用cur->vertexNumber之前,您不会通过检查cur == NULL来检查列表cur->vertexNumber 每次都会这样做。 您可以使用以下方法修复它:

while (cur && newNode->vertexNumber > cur->vertexNumber) {

“*”在哪里?

在整个代码中,您将间接引用附加到类型而不是变量 可能会产生误导。 为什么?

int* a, b, c;

上面你肯定没有声明三个指向int指针。 相反,您a a 声明为指向int的指针,将bc为简单整数。

int *a, b, c;

说清楚了。

显然,编译器不在乎,它忽略了'*'和变量名之间'*'空格,所以你所拥有的并没有错——这更多是一个人为因素/可读性问题。

其他事宜

如果您不使用size ,请将其从:

typedef struct linkedList{
    Node* head;
    int size;
} LinkedList;

此外,由于edgesvertices不能为负, sizexy也不能为负,因此将它们size_t而不是int 您将type与变量使用相匹配,在 x86_64 上,您将获得额外的 4 字节范围。

对你的代码采取另一种方法

理想情况下,您只想读取数据文件一次。 如果您动态分配指针而不是为LinkedList arrayOfLinkedLists[vertices];使用 VLA,则可以这样做LinkedList arrayOfLinkedLists[vertices]; 我会把它的实现留给你。 解决上述问题并稍微清理一下push()函数,您可以执行以下操作:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct node{
    size_t vertexNumber;
    struct node *next;
} Node;

typedef struct linkedList{
    Node *head;
    size_t size;
} LinkedList;

Node *createNode (size_t vertexNumber)
{
    Node *newNode = malloc (sizeof *newNode);
    
    if (!newNode) {
        perror ("malloc-newNode");
        return NULL;
    }
    
    newNode->vertexNumber = vertexNumber;
    newNode->next = NULL;
    
    return newNode;
}

int getNumberOfVerticesAndEdges (FILE *fp, size_t *vertices)
{
    size_t edges = 0, x, y;
    
    *vertices = 0;
    
    while (fscanf(fp, "%zu %zu", &x, &y) == 2) {
        if (x > *vertices)
            *vertices = x;
        if (y > *vertices)
            *vertices = y;

        edges += 1;
    }
    
    return edges;
}

/* add nodes in order of vertexNumber to each list */
Node *push (LinkedList *list, size_t vertex)
{
    Node *newNode = createNode(vertex);         /* create new node/initialize */
    
    if (!newNode)                               /* validate node */
        return NULL;
    
    list->size += 1;                            /* node allocated, increment count */
    
    if (!list->head) {                          /* if 1st node, node is head/tail */
        list->head = newNode;
        return list->head;
    }
    
    Node **pp = &list->head,                    /* iterate with address of pointer */
          *p  = list->head;                     /* and pointer to node */
    
    while (p) { /* loop over each node */
        if (vertex < p->vertexNumber) {         /* if new vertext less than current */
            *pp = newNode;                      /* replace current with new */
            newNode->next = p;                  /* set new->next to current */
            return newNode;
        }
        pp = &p->next;                          /* advance to next node */
        p = p->next;
    }
    
    return *pp = newNode;                       /* insert at end */
}

void printAdjacencyLists (LinkedList *arrayOfLinkedLists, size_t vertices)
{
    for (size_t i = 0; i < vertices; i++) {
        printf ("\n%zu:  ", i);
        
        if (arrayOfLinkedLists[i].head == NULL)
            return;
        
        Node *cur = arrayOfLinkedLists[i].head;
        
        while (cur){
            printf("%zu --> ", cur->vertexNumber);
            cur = cur->next;
        }
    }
    putchar ('\n');     /* tidy up with newline */
}

void freelists (LinkedList *a, size_t v)
{
    for (size_t i = 0; i < v; i++) {
        Node *node = a[i].head;
        while (node) {
            Node *victim = node;
            node = node->next;
            free (victim);
        }
    }
}

int main (int argc, char **argv){
    
    size_t edges = 0,
        vertices = 0,
        x, y;
    /* open filename provides as 1st argument, use default if none provided */
    FILE *fptr = fopen (argc > 1 ? argv[1] : "input-machine-problem-1.txt", "r");
    
    if (!fptr) {
        perror ("fopen-fptr");
        return 1;
    }

    if (!(edges = getNumberOfVerticesAndEdges (fptr, &vertices))) {
        fputs ("error: failed to read edges.\n", stderr);
        return 1;
    }
    
    /* initialize array of lists all zero/NULL */
    LinkedList arrayOfLinkedLists[vertices];
    memset (arrayOfLinkedLists, 0, sizeof arrayOfLinkedLists);

    for (size_t i = 0; i < vertices; i++) { 
        if (!fptr) {
            return 1;
        }
        rewind(fptr);
        for (size_t j = 0; j < edges; j++) {
            
            printf("%zu: ", j);
            if (fscanf (fptr, "%zu %zu", &x, &y) != 2) {
                fprintf (stderr, "error reading vertex: %zu, edge: %zu\n", i, j);
                return 1;
            }   
            printf ("%zu %zu ", x, y);
            
            if (i == x) {
                if (!push (&arrayOfLinkedLists[i], y))
                    return 1;
            }
            else if (i == y) {
                if (!push (&arrayOfLinkedLists[i], x))
                    return 1;
            }
            printf("**\n");
        }
    }
    fclose (fptr);

    printAdjacencyLists (arrayOfLinkedLists, vertices);
    
    freelists (arrayOfLinkedLists, vertices);
}

上面还包括一​​个freelists()函数,用于free()您为列表分配的所有内存。 始终确保您正在跟踪和释放您分配的内存。 这样,在分配main()以外的内容时,您不会造成内存泄漏。

示例组成输入/输出

使用示例顶点执行代码将产生以下输出:

$ ./bin/getverticies dat/edgelist.txt
0: 0 1 **
1: 2 3 **
2: 3 2 **
3: 1 0 **
0: 0 1 **
1: 2 3 **
2: 3 2 **
3: 1 0 **
0: 0 1 **
1: 2 3 **
2: 3 2 **
3: 1 0 **

0:  1 --> 1 -->
1:  0 --> 0 -->
2:  3 --> 3 -->

注意:文件名现在可以作为第一个参数传递给程序)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM