You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言链表队列程序读取访问违例异常的原因及修复咨询

Hey there! Let's break down what's going wrong with your linked list queue code and fix it step by step. The read access violation you're seeing comes from a mix of pointer mismatches, circular list logic, and type errors—let's go through each issue:

Key Issues in Your Code

1. Queue Initialization & Push Parameter Mismatch

In main, you initialize Queue *q = NULL; then call push(&q, "a");. But your push function expects a Queue * (pointer to Queue), while &q is a Queue ** (pointer to pointer to Queue). This causes the push function to write to invalid memory, corrupting your queue structure from the start.

2. Circular List Breaks Print Loop

In push, you set q->tail->next = q->head; which turns your queue into a circular linked list. But your print function uses while (temp != NULL) to traverse—since a circular list never hits NULL, this loop runs indefinitely, eventually accessing memory it shouldn't, triggering the read access violation.

3. Type & Memory Errors

  • Memory Leak + Wrong Data Handling: In push, you allocate memory for temp->data then immediately overwrite it with word, leaking the malloc'd memory. Also, in print, you use printf("%c\n", temp->data);—temp->data is a char* pointer, but %c expects a char value. You need to dereference the pointer with *temp->data.
  • Invalid Type in Pop: pop tries to assign a char* (q->head->data) to a char variable, which is a type mismatch. You should return a char* instead.

4. Duplicate Print Function

You have two identical void print(Queue *q) definitions—this will cause a compile error; delete one of them.

5. Wrong Cleanup in Delete Function

Your delete function calls delete(temp); (recursing on itself) instead of free(temp); to release node memory. This leads to infinite recursion or crashes.

6. Unchecked NULL in isEmpty

isEmpty directly accesses q->head without checking if q is NULL first. If q is NULL (like in the initial print call in main), this triggers a null pointer access.

Fixed Code

Here's the corrected version with comments highlighting key changes:

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

struct node_struct { 
    char *data; 
    struct node_struct *next; 
}; 
typedef struct node_struct Node; 

struct queue_struct { 
    Node *head, *tail; 
}; 
typedef struct queue_struct Queue; 

void push(Queue *q, char *word) { 
    Node* temp = (Node*)malloc(sizeof(Node));
    // Allocate enough memory for the word (including null terminator) and copy it
    temp->data = (char*)malloc(strlen(word) + 1);
    strcpy(temp->data, word);
    temp->next = NULL;

    if (q->head == NULL ) { 
        q->head = temp;
        q->tail = temp; // Initialize tail when first node is added
    } else { 
        q->tail->next = temp;
        q->tail = temp;
    }
    // Removed circular list logic - queues are FIFO, not circular
} 

char *pop(Queue *q) { 
    if (isEmpty(q)) {
        printf("Queue is empty!\n");
        return NULL;
    }
    Node* temp = q->head;
    char *n = temp->data; // Correct type: char* instead of char
    q->head = q->head->next;
    // If queue becomes empty after pop, reset tail
    if (q->head == NULL) {
        q->tail = NULL;
    }
    free(temp); // Free the node, not the data (we return the data to the caller)
    return n;
} 

void print(Queue *q) { 
    if (q == NULL || isEmpty(q)) { 
        printf("No Items\n");
        return;
    } 
    Node* temp = q->head;
    while (temp != NULL) { 
        printf("%s\n", temp->data); // Use %s to print strings, or %c if you want single chars
        // If you intended to store single chars, change data to char instead of char*
        temp = temp->next;
    } 
} 

int isEmpty(Queue *q) { 
    if (q == NULL || q->head == NULL) 
        return 1; 
    return 0; 
} 

void deleteQueue(Queue *q) { // Renamed to avoid conflict with keyword 'delete'
    if (q == NULL) return;
    Node* temp;
    while (q->head != NULL) { 
        temp = q->head;
        q->head = q->head->next;
        free(temp->data); // Free the data first
        free(temp); // Then free the node
    } 
    q->tail = NULL;
} 

int main(int argc, char **argv) { 
    Queue q; // Initialize a Queue instance, not a pointer to NULL
    q.head = NULL;
    q.tail = NULL;

    // Print the queue
    print(&q); 

    // Push items
    push(&q, "a"); 
    push(&q, "b"); 
    push(&q, "c"); 

    print(&q);

    // Cleanup
    deleteQueue(&q);
    return 0;
}

Additional Notes

  • I changed the queue initialization in main to use a stack-allocated Queue instead of a NULL pointer—this avoids the need for double pointers and makes initialization safer.
  • For push, I added proper string copying instead of just assigning the pointer (this prevents issues if the original word is modified or freed later).
  • Renamed delete to deleteQueue to avoid conflict with the C++ keyword (though you're using C, it's a good habit).
  • If you intended to store single characters instead of strings, you can change char *data in the Node struct to char data—then adjust push, pop, and print accordingly (no need to malloc for data, use %c in printf).

内容的提问来源于stack exchange,提问作者TaeXtreme

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 20:02:59