C语言Blackjack游戏开发遇Segmentation Fault及Invalid Read问题求助
Blackjack游戏C语言实现的指针与内存问题修复
问题背景
用C语言实现Blackjack游戏核心逻辑,定义了包含数值(Chiffre)和花色(Couleur)的Carte结构体,通过calloc分配可存储52张卡牌的数组,编写了TestPaire(检测是否有对子)和CompteCarte(计算卡牌总和)两个函数,但运行时出现Invalid read of size 4错误、WSL下触发Segmentation Fault,控制台先输出10后显示0。
核心错误分析
- sizeof的误用:函数中
sizeof(*Jeu)获取的是指针类型的大小(比如64位系统是8字节),不是数组的元素个数。主函数仅初始化了前3张牌,但函数循环次数是指针大小的数值,导致访问未初始化的内存区域,触发越界读取错误。 - 循环变量错误:
TestPaire的内层循环中,错误地将j++写成了i++,导致外层循环变量i被无限制递增,直接越界访问内存引发段错误。 - 参数设计缺陷:没有传递当前手牌的实际数量,依赖
sizeof获取数组长度的方式在指针参数中完全失效——当数组名作为参数传递给函数时,会退化为指针,无法通过sizeof获取原数组的长度。
修正后的代码
结构体定义
typedef struct Carte { int Chiffre; char Couleur[10]; } Carte;
修正后的CompteCarte函数
// 新增参数nb_cartes:当前手牌的实际数量 int CompteCarte(Carte *Jeu, int nb_cartes) { int compteur = 0; for (int i = 0; i < nb_cartes; i++) { compteur += Jeu[i].Chiffre; } return compteur; }
修正后的TestPaire函数
// 新增参数nb_cartes:当前手牌的实际数量 int TestPaire(Carte *Jeu, int nb_cartes) { for (int i = 0; i < nb_cartes; i++) { // 内层循环从i+1开始,避免重复比较 for (int j = i + 1; j < nb_cartes; j++) { if (Jeu[i].Chiffre == Jeu[j].Chiffre) { return 1; } } } return 0; }
修正后的主函数
#include <stdio.h> #include <stdlib.h> int main(int argc, char const *argv[]) { Carte* Jeu = (Carte*)calloc(52, sizeof(Carte)); if (Jeu == NULL) { // 新增内存分配失败的检查 fprintf(stderr, "Erreur d'allocation mémoire\n"); return 1; } Jeu[0].Chiffre = 3; Jeu[1].Chiffre = 1; Jeu[2].Chiffre = 6; int nb_cartes_joueur = 3; // 明确当前手牌数量 int a = CompteCarte(Jeu, nb_cartes_joueur); printf("%d\n", a); // 输出应为10 int b = TestPaire(Jeu, nb_cartes_joueur); printf("%d\n", b); // 输出应为0,因为没有对子 free(Jeu); // 释放动态分配的内存 return 0; }
关键建议
- 动态数组必须传递长度参数:所有操作动态数组的函数,都需要额外传入数组的实际元素个数,不能依赖
sizeof计算长度。 - 循环变量严格检查:编写嵌套循环时,注意循环变量的递增逻辑,避免出现笔误导致的无限循环或越界。
- 内存分配后检查:使用
calloc/malloc分配内存后,必须检查返回值是否为NULL,避免空指针访问。 - 指针使用简化:主函数中
Jeu是Carte*类型,直接传递Jeu即可(无需&Jeu),函数参数用Carte*接收,更符合数组的使用逻辑,避免不必要的二级指针复杂度。
内容的提问来源于stack exchange,提问作者DilDeath
相关产品推荐
相关产品推荐

