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

C语言双向链表实现音乐播放器选择播放曲目时程序崩溃排查

基于双向链表实现的音乐播放器运行崩溃排查

我做学校课程项目的小型音乐播放器,要求必须用链表存储数据,目前代码编译无警告但运行时会触发崩溃,其中用于遍历展示链表的View_List(原函数名Afficher_Liste)运行正常。

相关代码片段

音轨结构体定义

typedef struct Piste{
    char *pTitle;
    char *pArtist;
    char *pPath;
    struct Piste *pNext;
    struct Piste *pPrev;
}Piste;

存在问题的播放功能函数

void Play_Music(Piste **pHead){

    int choice;
    int ctr = 1;
    char * path_music;

    path_music= (char*)malloc(200 * sizeof(char));

    View_List(&ppDL);

    Piste *pCur = *pHead;


    printf("What music you want to play ?");
    scanf("%d",&choice);

    while(choix!=cptr){
        pCur = pCur->pNext;
        ctr++;
        if(choice==cptr){
            path_music= pCur->pPath;
        }
    }
    printf("your choice is %s",path_music);
    scanf("%d",choice);
}

调用播放函数的用户菜单代码

void User_Mode(){

    int choice;
    char *search= NULL;

    while(choice!= 4)
    {
        system("cls");

        printf("---------- User Menu----------\n\n");
        printf("1 - Search\n");
        printf("2 - Play a music\n");
        printf("3 - Back to menu\n");
        printf("your choice?\n");
        scanf("%d", &choice);

        switch(choice){

        case 1:
            fflush(stdin);
            search = (char*)malloc(200 * sizeof(char));
            printf( "what do you want to listen  ? : \n" );
            scanf( "%[^\n]", seach);
            fgetc( stdin );
            if(search!=NULL){
                search_music(search,&ppDL);
            }

            break;
        case 2:
            play_music();
            break;
        case 3:
            main_menu();
            break;
        default:
            system("cls");
            printf("your choice isnt good\n\n");
            user_mode();
        }
    }
}

崩溃原因汇总

全是代码笔误+边界判断缺失导致的,逐个对应修改即可:

  • 变量名拼写错误直接导致逻辑跑飞:循环条件写的是while(choix!=cptr),实际定义的计数器是ctr、存储用户输入的变量是choice,两个变量名全拼错。编译没报错是因为旧C标准会对未声明的变量默认按int类型处理,运行时直接读取随机野值,循环要么不执行要么无限死循环。
  • 链表遍历完全没做空指针判断:循环里直接执行pCur = pCur->pNext,如果用户输入的序号超过链表总长度,pCur走到链表尾部的NULL之后,下一次访问pCur->pNext就是直接访问空指针,必然触发崩溃。另外初始计数器ctr设为1,用户输入1的时候循环根本不会进入,拿不到第一个节点的路径数据。
  • 内存泄漏+野指针问题:一开始给path_music申请了200字节的堆内存,找到对应节点后又直接把path_music指针指向节点内的pPath地址,之前申请的内存没有释放也没有指针指向,直接造成内存泄漏。
  • 函数调用和定义完全不匹配:定义的Play_Music需要传入双向链表头指针的二级指针,结果菜单case2里调用的时候直接写play_music(),既没传参数,函数名大小写也不对(C语言大小写敏感),等于直接跳转到未知内存地址执行。
  • 末尾的scanf写法错误:最后一行scanf("%d",choice);没有传入变量地址,直接把用户输入的整数值当内存地址写入,触发非法内存访问崩溃。
  • 菜单逻辑存在多处笔误:搜索功能里scanf( "%[^\n]", seach);把search拼成了seach,属于写入野指针;choice变量定义后没有初始化就进入while(choice!=4)的判断,初始值是随机垃圾值,逻辑完全不可控。
  • 函数参数传了没用:View_List(&ppDL);直接写死了全局变量,根本没用到传入的pHead参数,参数定义完全多余。

顺带提一句,fflush(stdin)属于C标准未定义行为,不要用来清空输入缓冲区,用循环读取剩余字符的方式更稳妥。

修复参考

修复后的播放函数

void Play_Music(Piste **pHead){
    // 先判断链表是否为空
    if (pHead == NULL || *pHead == NULL) {
        printf("当前播放列表为空!\n");
        getchar();getchar();
        return;
    }

    int choice;
    int ctr = 1;
    int list_len = 0;
    Piste *pCur = *pHead;

    // 先统计链表总长度,校验用户输入范围
    while(pCur != NULL) {
        list_len++;
        pCur = pCur->pNext;
    }
    pCur = *pHead;

    View_List(pHead);

    printf("请输入要播放的音乐序号(1-%d):", list_len);
    scanf("%d",&choice);

    if (choice <1 || choice > list_len) {
        printf("输入的序号无效!\n");
        getchar();getchar();
        return;
    }

    // 遍历定位到目标节点
    while(ctr != choice){
        pCur = pCur->pNext;
        ctr++;
    }

    printf("你选择的音乐路径为:%s\n", pCur->pPath);
    // 这里补充实际调用系统API播放音频的逻辑即可

    printf("按回车键返回菜单...");
    getchar();getchar();
}

菜单部分对应修改

  • 定义choice时直接初始化为0,避免初始野值
  • 搜索功能里的seach笔误改为search
  • case2的调用改为Play_Music(&ppDL);
  • 删掉播放函数末尾多余的错误scanf代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 14:57:29