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

为什么我的C语言简单程序在case '2'的break语句处崩溃

程序分支退出时崩溃问题排查

我的程序刚好在case '2'的break语句处崩溃,该case下的代码都能正常执行,但到break语句就崩溃非常奇怪,理论上程序应该回到循环继续运行。

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

#define nullptr ((void*)0)

typedef unsigned char byte;         // 8位数值类型
#define max 255
#define cap 256

typedef struct Elemento Elemento;
struct Elemento {
    char* valor;
    byte prioridade;
    bool isvalid;
};

typedef struct {
    short comprimento;
    Elemento elementos[cap];
} Lista;

void inicializa (Lista* q) {        // 初始化队列
    q->comprimento = 0;
}

void ordena (Lista *q) {
    short i;
    for (i = 1; i < q->comprimento; i ++) {
        Elemento e = q->elementos[i];
        short j;
        for (j = i - 1;
            j >= 0 && q->elementos[j].prioridade < e.prioridade;
            j --) {
            strcpy(q->elementos[j + 1].valor, q->elementos[j].valor);
            q->elementos[j + 1].prioridade = q->elementos[j].prioridade;
        }
        q->elementos[j + 1] = e;
    }
}

void enfileira (Lista* q, Elemento *s, byte p) {      // 元素入队
    if (q->comprimento != cap) {
        q->elementos[q->comprimento].valor = (char *) malloc(strlen(s->valor)*sizeof(char));
        strcpy(q->elementos[q->comprimento].valor, s->valor);
        q->elementos[q->comprimento].prioridade = p;
        q->elementos[q->comprimento].isvalid = true;
 
        q->comprimento ++;
        if (q->comprimento > 1) ordena(q);
    }
}

Elemento primeiro (Lista* q) {     // 获取队首元素
    Elemento e;
    if (q->comprimento != 0) {
        e.isvalid = true;
        strcpy(e.valor, q->elementos[0].valor);
        return e;
    }
    e.isvalid = false;
    return e;
}

Elemento remova (Lista* q) {       // 队首元素出队
    Elemento e;
    if (q->comprimento != 0) {
        e.isvalid = true;
        strcpy(e.valor, q->elementos[0].valor);

        byte i;
        for (i = 0; i < q->comprimento - 1; i ++) {
            strcpy(q->elementos[i].valor, q->elementos[i + 1].valor);
            q->elementos[i].prioridade = q->elementos[i + 1].prioridade;
        }
        q->comprimento --;
        return e;
    }
    e.isvalid = false;
    return e;
}

short comprimento (Lista* q) {       // 获取队列长度
    return q->comprimento;
}

void reinicializa (Lista* q) {      // 重置队列
    q->comprimento = 0;
}

void finaliza (Lista* q) {      // 销毁队列
}

int main () {
    Lista s;
    Elemento e; e.valor = nullptr;
    char *string = nullptr;
    float valor;
    byte prioridade;
    short buffer_tam, string_tam;

    byte input;
    do {
        printf("operacao: ");
        string_tam = getline(&string, &buffer_tam, stdin);

        switch (string[0]) {
            case '1':
                inicializa(&s);
                break;
            
            case '2':
                string_tam = getline(&e.valor, &buffer_tam, stdin);
                e.valor[string_tam - 1] = '\0';
                scanf("%hhu", &prioridade);
                enfileira(&s, &e, prioridade);
                break;

            case '3':
                printf("%s\n", primeiro(&s).valor);
                break;

            case '4':
                printf("%s\n", remova(&s).valor);
                break;

            case '5':
                printf("%hi\n", comprimento(&s));
                break;

            case '6':
                reinicializa(&s);
                break;

            case '7':
                finaliza(&s);
                break;
        }

    } while (string[0] != '0');

    return 0;
}

该问题可能在其他环境下无法复现,常规搜索也难以定位到对应原因。

问题根因与解决方案

  • 调整分支判断逻辑无法解决问题:将switch替换为if语句后,程序仍然会在退出分支时崩溃
  • 根因定位:输入处理逻辑混用getline和scanf,两种输入函数对缓冲区的处理逻辑不同,导致换行符残留、后续内存操作异常
  • 修复方法:将case '2'中的scanf调用替换为getline读取优先级数值,程序即可正常运行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 21:15:03