结构体中整数数组无法释放的问题排查求助
树形结构内存释放错误排查与解决
问题场景
实现最多包含9个子节点的树形结构,将已初始化子节点的索引存入与子节点数量匹配的整数数组,释放该数组时触发堆内存错误。可编译的代码片段如下:
#include <stdio.h> #include <stdlib.h> #include <string.h> struct moveNode { int rating; // char player; int numPossibleMoves, *possibleMoves; struct moveNode **children; }; struct moveNode *moveTreeHead; struct moveNode *createHeadNode(void); void initializeNode(struct moveNode *node, char *boardState); int main() { moveTreeHead = createHeadNode(); printf("moveTreeHead->possibleMoves[1] %d\n", moveTreeHead->possibleMoves[1]); free(moveTreeHead->possibleMoves); } void initializeNode(struct moveNode *node, char *boardState) { int i, possibleMovesCounter = -1; node->numPossibleMoves = 0; for (i = 0; i < 9; i++) { if (boardState[i] != 'x' && boardState[i] != 'o') { node->numPossibleMoves++; } } if (node->numPossibleMoves != 0) { node->possibleMoves = (int *)malloc(sizeof *(node->possibleMoves)); for (i = 0; i < 9; i++) { if (boardState[i] != 'x' && boardState[i] != 'o') { possibleMovesCounter++; node->possibleMoves[possibleMovesCounter] = i; node->children[i] = (struct moveNode *)malloc(sizeof *(node->children[i])); node->children[i]->numPossibleMoves = 0; } } } else { node->possibleMoves = NULL; } } struct moveNode *createHeadNode() { struct moveNode *ret = (struct moveNode *)malloc(sizeof(struct moveNode)); ret->children = (struct moveNode **)malloc(sizeof *(ret->children) * 9); initializeNode(ret, "012345678"); return ret; }
错误信息
运行时触发堆内存检测错误:
warning: HEAP[helloworld.exe]: warning: Heap block at 0000028AA9C23530 modified at 0000028AA9C23544 past requested size of 4 Thread 1 received signal SIGTRAP, Trace/breakpoint trap. 0x00007ffa1046a773 in ntdll!RtlRegisterSecureMemoryCacheCallback () from C:\WINDOWS\SYSTEM32\ntdll.dll
错误原因分析
错误提示核心是堆内存块被修改超出了申请的大小,问题出在initializeNode函数中:
- 传入的
boardState为"012345678"时,所有字符都不是x或o,因此node->numPossibleMoves被计算为9。 - 但分配
possibleMoves数组时,仅执行malloc(sizeof *(node->possibleMoves)),也就是只分配了1个int的内存(通常为4字节)。 - 后续循环中给
possibleMoves[0]到possibleMoves[8]赋值,会越界写入堆内存中不属于该数组的区域,破坏堆结构,最终在free时触发检测错误。
修复方案
修改possibleMoves的内存分配代码,根据numPossibleMoves的实际值分配对应大小的内存:
将原来的:
node->possibleMoves = (int *)malloc(sizeof *(node->possibleMoves));
替换为:
node->possibleMoves = (int *)malloc(sizeof(int) * node->numPossibleMoves);
修复后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> struct moveNode { int rating; // char player; int numPossibleMoves, *possibleMoves; struct moveNode **children; }; struct moveNode *moveTreeHead; struct moveNode *createHeadNode(void); void initializeNode(struct moveNode *node, char *boardState); int main() { moveTreeHead = createHeadNode(); printf("moveTreeHead->possibleMoves[1] %d\n", moveTreeHead->possibleMoves[1]); free(moveTreeHead->possibleMoves); // 补充释放children节点和根节点,避免内存泄漏 for (int i = 0; i < 9; i++) { free(moveTreeHead->children[i]); } free(moveTreeHead->children); free(moveTreeHead); } void initializeNode(struct moveNode *node, char *boardState) { int i, possibleMovesCounter = -1; node->numPossibleMoves = 0; for (i = 0; i < 9; i++) { if (boardState[i] != 'x' && boardState[i] != 'o') { node->numPossibleMoves++; } } if (node->numPossibleMoves != 0) { node->possibleMoves = (int *)malloc(sizeof(int) * node->numPossibleMoves); for (i = 0; i < 9; i++) { if (boardState[i] != 'x' && boardState[i] != 'o') { possibleMovesCounter++; node->possibleMoves[possibleMovesCounter] = i; node->children[i] = (struct moveNode *)malloc(sizeof *(node->children[i])); node->children[i]->numPossibleMoves = 0; } } } else { node->possibleMoves = NULL; } } struct moveNode *createHeadNode() { struct moveNode *ret = (struct moveNode *)malloc(sizeof(struct moveNode)); ret->children = (struct moveNode **)malloc(sizeof *(ret->children) * 9); initializeNode(ret, "012345678"); return ret; }
内容的提问来源于stack exchange,提问作者mkdrive2
相关产品推荐
相关产品推荐

