C语言:含重复指针数组的结构体指针指向异常且出现垃圾值
问题原因
createShoeFromDecks函数的参数是值传递,传入的deckOfCards是main函数中deckOfCards的临时副本。当函数执行完毕返回时,这个临时副本会被销毁,内存被释放。此时shoe中存储的所有卡片指针都指向了已经被释放的内存区域,属于野指针,访问时就会读取到随机的垃圾值。
解决方案
方案1:传递deck的指针(推荐,节省内存)
修改createShoeFromDecks的参数为指针类型,直接使用原deck的内存地址,避免临时副本被销毁:
static shoe createShoeFromDecks(deck *deckOfCards) { shoe shoeOfCards; for (int nShoe = 0; nShoe < DECKAMOUNT; nShoe++) { uint offset = CARDSINADECK * nShoe; for (int rankNumer = 0; rankNumer < CARDSINADECK; rankNumer++) { uint posInArray = rankNumer + offset; // 取原deck中卡片的地址 card *cardptr = &deckOfCards->cards[rankNumer]; shoeOfCards.cards[posInArray] = cardptr; } } return shoeOfCards; }
同时修改main函数中的调用方式,传入原deck的地址:
shoe shoeOfCards = createShoeFromDecks(&deckOfCards);
方案2:让shoe存储card结构体副本(更安全,无需关注生命周期)
修改shoe的结构体定义,将指针数组改为card结构体数组:
typedef struct shoe { uint topOfShoe; card cards[CARDSINASHOE]; // 直接存储card结构体,而非指针 } shoe;
然后修改createShoeFromDecks函数,直接复制card结构体:
static shoe createShoeFromDecks(deck deckOfCards) { shoe shoeOfCards; for (int nShoe = 0; nShoe < DECKAMOUNT; nShoe++) { uint offset = CARDSINADECK * nShoe; for (int rankNumer = 0; rankNumer < CARDSINADECK; rankNumer++) { uint posInArray = rankNumer + offset; // 复制card结构体到shoe中 shoeOfCards.cards[posInArray] = deckOfCards.cards[rankNumer]; } } return shoeOfCards; }
最后修改main函数中的printf语句,直接访问结构体成员(不再用指针箭头):
printf("%d %d \n", shoeOfCards.cards[i].rank, shoeOfCards.cards[i].suit);
方案对比
- 方案1:内存占用小(仅存储指针),但需要保证原deck的生命周期长于shoe,否则仍会出现野指针问题。
- 方案2:内存占用更大(复制8副牌的所有card结构体),但shoe的生命周期独立,无需依赖原deck,安全性更高。
内容的提问来源于stack exchange,提问作者Peter Petigru
相关产品推荐
相关产品推荐

