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

指针与scanf引发访问违规问题排查求助

商品出入库程序访问违规问题排查

问题背景

我写的这段代码原本要实现:输入商品名称、出入库标识(单个字母,如i=入库、o=出库)和转移数量,输入"FINE"时程序结束。但现在保存商品数量时出现访问违规,找不到问题所在,求帮忙排查:

原代码

#define MAX 20
#define END "FINE"

typedef struct type_struct {
    char name[MAX];
    char move[2];
    int quantity;
    struct type_struct* next;
}type;

void insert(type* p) {

    type* aux;

    aux = p;
    while (aux != NULL) 
        aux = aux->next;
    
    aux = malloc(sizeof(type));

    printf("name of good: ");
    scanf("%s", aux->name);
    getchar();
    printf("in or out?: ");
    scanf("%c", aux->move);
    
    printf("quantity: ");
    scanf("%d", aux->quantity);
    printf("\n");

}

int main(void) {

    type* phrase=NULL;
    char fine[5];

    strcpy(fine, END);

    do {
        insert(phrase);
    } while ((strcmp(phrase, fine) == 0));

}

错误点分析与修复

  1. 核心访问违规原因:读取数量时scanf("%d", aux->quantity);传参错误,scanf读整数需要传入变量地址,应该改成scanf("%d", &aux->quantity);。直接传aux->quantity会把输入的数值当成内存地址写入,必然触发访问违规。

  2. 链表插入逻辑失效:

    • insert函数的参数是type* p,属于值传递,main里的phrase永远是NULL,新节点根本无法链接到链表上。需要把参数改成指针的指针type** p,才能修改外部的链表头指针。
    • 找到链表尾后malloc的新节点,没有把它链接到原链表的尾部,导致链表永远无法正常构建。
  3. 循环结束条件完全错误:strcmp(phrase, fine)是把链表指针和字符串数组比较,类型不匹配,逻辑完全不成立。应该在输入商品名称时判断是否为"FINE",如果是就终止程序。

  4. 野指针问题:malloc新节点后没有初始化next指针为NULL,可能导致后续链表遍历出现未知错误。

修复后的完整代码

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

#define MAX 20
#define END "FINE"

typedef struct type_struct {
    char name[MAX];
    char move[2];
    int quantity;
    struct type_struct* next;
} type;

void insert(type** p) {
    type* aux = *p;
    // 定位到链表最后一个节点
    while (aux != NULL && aux->next != NULL) {
        aux = aux->next;
    }

    type* new_node = malloc(sizeof(type));
    if (!new_node) {
        printf("内存分配失败\n");
        return;
    }
    new_node->next = NULL; // 初始化next指针

    printf("输入商品名称(输入FINE结束):");
    scanf("%s", new_node->name);

    // 判断是否触发结束条件
    if (strcmp(new_node->name, END) == 0) {
        free(new_node);
        *p = NULL; // 告诉main循环终止
        return;
    }

    printf("出入库标识(i/o):");
    scanf("%s", new_node->move);
    new_node->move[1] = '\0'; // 确保字符串合法

    printf("转移数量:");
    scanf("%d", &new_node->quantity);
    printf("\n");

    // 将新节点加入链表
    if (*p == NULL) {
        *p = new_node;
    } else {
        aux->next = new_node;
    }
}

int main(void) {
    type* phrase = NULL;
    do {
        insert(&phrase);
    } while (phrase != NULL);

    // 清理链表内存,避免泄漏
    type* temp;
    while (phrase != NULL) {
        temp = phrase;
        phrase = phrase->next;
        free(temp);
    }

    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 20:16:09