【发布时间】:2014-12-29 06:04:12
【问题描述】:
我有一个 C 语言的纸牌游戏(我必须在 C 类项目中制作它)。我创建了一种将结构从一个动态数组移动到另一个的方法。不幸的是,该方法起初有效,但后来当我在程序中调用它时,它开始抛出 malloc() 错误。 Deck 是一个结构体,包含一个int size 和一个动态分配的Card *deck,而Card 是一个用于存放单张卡片的结构体。有什么我遗漏的东西,或者必须以其他方式定义吗?
void moveCard(Deck *src, Deck *dest, int n){
Card *tmpCards = NULL;
Card tmp = (*src).deck[n]; // get card to be copied
int newSize = dest->size + 1; //increase dest size by 1
tmpCards = (Card *) malloc(sizeof(Card) * newSize); // allocate new memory area
memmove(&(tmpCards[0]), &(dest->deck[0]), sizeof(Card) * (newSize - 1));
// copy all the cards from old memory area to new area
dest->deck = tmpCards; // reassign old pointer to new memory area
dest->size = newSize; // reevaluate size
dest->deck[newSize - 1] = tmp; // copy card to end of new area
tmpCards = NULL; // empty out pointer (no functionality, just for easier reading)
newSize = src->size; // reevaluate newSize
tmpCards = (Card *) malloc(sizeof(Card) * (newSize - 1));
// allocate smaller mem area by 1
memmove(&(tmpCards[0]),&(src->deck[0]), sizeof(Card) * (n));
// copy all cards up to the n-th point
memmove(&(tmpCards[n]),&(src->deck[n+1]), sizeof(Card) * (newSize - n));
// copy all cards from the n+1 -th point
src->size = newSize -1; // reevaluate size
src->deck = tmpCards; // reassign pointer
// since all input parameters were pointers, no return is necessary
}
编辑:对我不释放内存这一事实的关注的人。原始代码中有 2 个免费命令(free(dest->deck) 和 free(src->deck))。但只有其中一个有效。另一个出于某种奇怪的原因再次造成了内存损坏,所以我发现它更好,而不是把它们放在这个例子中。
【问题讨论】:
-
第1点,请do not cast
malloc()的返回值。第2点。你不能用realloc()吗? -
在分配
tmpCards之前,您不应该释放旧的dest->deck吗?还是它还没有指向任何东西? -
如果您知道任何一副牌可能包含的最大卡片数量,而且这不是一个大得离谱的数字,您可以考虑使用固定大小的
deck数组,其中size表示使用了多少,而不是每次移动卡时都不断重新分配内存……它可能会大大提高性能。 -
“另一个出于某种奇怪的原因再次造成了内存损坏” - 不,您 造成了内存损坏,
free()只是提醒您注意这一事实。你需要解决这个问题。 -
malloc 中的错误可能是由之前执行的程序的完全不同部分的内存损坏引起的。如果您有缓冲区溢出并在分配的内存之外写入,您可能会破坏 malloc 系统的内部数据结构,并在很久以后发生崩溃。因此,这样的程序片段有时在调试时并没有多大用处。使用调试器或类似 valgrind 的工具来查找您的实际问题。