C语言基于malloc与指针实现的Card牌组程序运行频繁触发段错误,求排查
你当前代码触发段错误的核心是内存计算错误、野指针操作、代码作用域错位三类问题,逐点修正如下:
堆内存分配大小计算错误
代码中写的Card * deck=malloc(DECK_SIZE * sizeof(char));逻辑完全错误:你需要申请的是连续52个Card结构体的内存空间,结果把大小算成了52个char类型的长度(仅52字节)。64位系统下单个Card包含3个char*指针,每个指针占8字节,单个结构体就需要24字节,你当前申请的内存量仅为实际需求的1/24,后续通过下标访问deck[i]时会直接越界触碰非法内存。
修正写法:Card *deck = malloc(DECK_SIZE * sizeof(Card));,同时补充malloc返回值判空逻辑,避免分配失败时操作空指针。野指针直接写操作触发崩溃
结构体中定义的suit、colour是char*类型的指针,本身没有指向任何可写的合法内存地址,你直接调用strncpy(deck[i].suit, suits[i/RANKS], MAX)向这个随机指向的地址写数据,是触发段错误的最直接原因。
修正方向:把结构体里的suit、colour从裸指针改成定长字符数组,比如char suit[MAX]; char colour[MAX];,让每个Card结构体自带存储字符串的连续空间,不需要额外给指针申请堆内存,从根源上避免野指针问题。代码作用域与逻辑结构错位
当前的for循环、函数大括号完全配对错误:循环刚完成第一次迭代、给deck[0].rank赋值后,就直接执行了return deck;语句,后续的花色赋值、剩余51张牌的初始化代码完全无法执行,属于语法层面的逻辑嵌套错误。
修正写法:把所有卡牌初始化逻辑完整放在for循环体内,等循环执行完全部52张牌的赋值后,再在循环外执行return语句返回deck指针。遗漏字段初始化
你在Card结构体中定义了colour字段,但全程没有给这个字段赋值,后续如果读取该字段内容会拿到未初始化的野指针,需要在循环里根据花色规则补全对应赋值:黑桃、梅花对应黑色,红桃、方块对应红色。
修正后的核心可运行片段
// 调整后的结构体定义 typedef struct { char *rank; char suit[MAX]; char colour[MAX]; }Card; Card* make_deck() { char *ranks[] = { "King", "Queen", "Jack", "10", "9", "8", "7", "6", "5", "4", "3", "2", "Ace" }; char *suits[] = { "Spades", "Clubs", "Hearts", "Diamonds" }; // 修正内存分配大小 Card *deck = malloc(DECK_SIZE * sizeof(Card)); if (deck == NULL) { perror("malloc failed"); return NULL; } // 修正循环作用域,包裹所有赋值逻辑 for(int i=0;i<DECK_SIZE;i++){ deck[i].rank = ranks[i%RANKS]; strncpy(deck[i].suit, suits[i/RANKS], MAX); // 补全颜色字段赋值 if (i/RANKS <2) { strcpy(deck[i].colour, "Black"); } else { strcpy(deck[i].colour, "Red"); } } // 循环结束后再返回 return deck; }
内容的提问来源于stack exchange,提问作者Keshav

