C语言终端贪吃蛇realloc扩容触发double free or corruption错误求助
问题排查与修复方案
触发内存错误的核心原因
- append函数设计错误,realloc新地址未回传
你定义的append函数声明返回int*类型,但内部没有返回值,且C语言为值传递,函数内修改形参v不会更新外部实参的direction指针。当realloc申请新内存块并释放旧块后,外部的direction仍指向已被释放的旧内存,成为野指针,后续访问、扩容或最终执行free时就会触发内存损坏错误。 - 内存分配单位错误
所有动态内存分配代码中,你均使用sizeof(int*)(指针类型大小)作为分配单位,但你存储的是int类型的方向值,应改为sizeof(int)。该问题会引发隐式内存越界,是内存 corruption 的常见诱因。 - 多线程共享变量未同步
子线程会直接修改*direction的值,主线程会调用realloc修改direction本身的指向,两个线程未加互斥锁同步,会导致子线程可能访问已释放的旧地址,引发非法内存访问。
具体修复代码
1. 修复append函数
int *append(int *v, int size, int value) // append data to vector { size = size + 1; puts("Reallocing memory ..."); printf("\nCurrent size: %d\n", size); // 修改分配单位为sizeof(int),新增空指针判断 int *new_v = (int*)realloc(v, size * sizeof(int)); if (new_v == NULL) { perror("realloc failed"); exit(EXIT_FAILURE); } puts("Memory reallocating sucessful!"); new_v[size-1] = value; return new_v; // 返回新指针 }
2. 调整append调用逻辑
由于需要修改外部的direction指针,你需要将updateGame函数的direction参数改为二级指针,或者将append的返回值回传给原指针:
// updateGame函数参数改为二级指针 void updateGame(char game[SIZE_X][SIZE_Y], position *player_position, int **direction, int it, int *length) { // 原有逻辑不变,仅修改append调用行 if (game[i][j] == '+') { *length = *length+1; *direction = append(*direction, *length, (*direction)[it]); } // 其余访问direction的地方也要对应调整为(*direction)[xxx] }
3. 修复初始内存分配
将main函数中初始分配direction的代码修改为:
int *direction = (int*)malloc(1*sizeof(int)); // 分配单位改为int大小
4. 新增互斥锁同步线程
// 全局新增互斥锁定义 pthread_mutex_t dir_mutex = PTHREAD_MUTEX_INITIALIZER; // 子线程修改direction时加锁 void *readMove(void *data) { int *direction = ((int*) data); pthread_detach(pthread_self()); while (collision) { if (getch() == '\033') { // 原有按键处理逻辑不变,仅修改赋值部分 pthread_mutex_lock(&dir_mutex); switch(getch()) { case 'A': *direction = 0; break; case 'B': *direction = 2; break; case 'C': *direction = 1; break; case 'D': *direction = 3; break; } pthread_mutex_unlock(&dir_mutex); // 其余清屏逻辑不变 } } pthread_exit(NULL); } // 主线程访问direction时也要加锁
其他需修复的逻辑错误
- main函数中循环变量
i从未自增,调用updateGame时传入的it永远为0,导致蛇的身体永远不会按照历史方向移动,需要在每次调用updateGame后执行i++,同时注意数组访问越界判断。 - 子线程当前修改的是
direction[0],但你的direction数组存储的是每一步的历史方向,需要调整为修改最新的方向值,否则按键操作不会生效。
内容的提问来源于stack exchange,提问作者Leonardo Araujo
相关产品推荐
相关产品推荐

