C程序调试模式正常运行、正常模式崩溃问题(已解决)
问题定位与修复方案
嘿,我一眼就揪出了导致你代码崩溃的核心问题——这是个非常经典的内存分配错误,刚好能解释为什么调试模式能跑但正常模式会崩溃:
在CreatePerson函数的第一行内存分配代码里:
newPerson=(Person*)malloc(sizeof(newPerson));
这里newPerson是个指针(Person*类型),所以sizeof(newPerson)得到的只是指针本身的大小(通常是4或8字节,取决于你的系统是32位还是64位),而不是Person结构体实际需要的内存空间。这就导致你只分配了一小块内存,根本装不下整个Person结构体的所有成员。
调试模式下,编译器会给内存分配额外的“保护填充”和检测机制,所以即使你越界访问内存,也不会立刻触发崩溃;但发布模式下没有这些保护,当你尝试给numOfKids、kids这些结构体成员赋值时,就会写到不属于你的内存区域,直接触发崩溃。
具体修复步骤
1. 修正结构体内存分配
把上面的错误代码改成:
newPerson = malloc(sizeof(Person));
(顺便提一句:在C语言里完全不需要强制转换malloc的返回值,强制转换反而可能隐藏一些潜在的类型问题,比如忘记包含stdlib.h导致的隐式声明错误)
2. 修复内存泄漏问题
你的代码在分配失败时直接返回NULL,但没有释放已经分配的内存(比如newPerson->name或者已经分配好的部分kids数组元素),这会导致内存泄漏。比如如果分配某个kids[i]失败,之前分配的newPerson、newPerson->name以及前面的kids[0]到kids[i-1]都会变成无法释放的内存垃圾。
可以在每个错误分支里手动清理已分配的资源,比如:
- 当
newPerson->kids分配失败时:if (newPerson->kids==NULL){ free(newPerson->name); free(newPerson); return NULL; } - 当某个
kids[i]分配失败时:if (newPerson->kids[i]==NULL){ // 先释放已经分配的所有kids元素 for (int j=0; j<i; j++){ free(newPerson->kids[j]); } free(newPerson->kids); free(newPerson->name); free(newPerson); return NULL; }
3. 其他潜在优化点
scanf("%s", tempName)存在缓冲区溢出风险,建议改成scanf("%255s", tempName)(假设MAX_NAME是256),限制输入长度,避免超出tempName的数组大小。- 确保
InitPersonValues函数正确初始化结构体的所有成员(比如把kids指针初始化为NULL),避免出现野指针。
修正后的完整代码示例
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_NAME 256 typedef struct { char* name; int id; int numOfKids; char** kids; } Person; void InitPersonValues(Person* p) { p->name = NULL; p->id = 0; p->numOfKids = 0; p->kids = NULL; } Person* CreatePerson(){ Person* newPerson = malloc(sizeof(Person)); if (newPerson == NULL){ return NULL; } InitPersonValues(newPerson); char tempName[MAX_NAME]; int id; int kidsNumber; printf("Name:\n"); // 限制输入长度,防止缓冲区溢出 scanf("%255s", tempName); newPerson->name = malloc(1 + strlen(tempName)); if (newPerson->name == NULL){ free(newPerson); return NULL; } strcpy(newPerson->name, tempName); printf("ID:\n"); scanf("%d", &id); newPerson->id = id; printf("Num of kids:\n"); scanf("%d", &kidsNumber); newPerson->numOfKids = kidsNumber; if (kidsNumber > 0){ newPerson->kids = malloc(kidsNumber * sizeof(char*)); if (newPerson->kids == NULL){ free(newPerson->name); free(newPerson); return NULL; } for (int i=0; i<kidsNumber; i++){ printf("Kid #%d name:\n", i+1); scanf("%255s", tempName); newPerson->kids[i] = malloc(strlen(tempName) + 1); if (newPerson->kids[i] == NULL){ // 清理已分配的资源 for (int j=0; j<i; j++){ free(newPerson->kids[j]); } free(newPerson->kids); free(newPerson->name); free(newPerson); return NULL; } strcpy(newPerson->kids[i], tempName); printf("%s\n", newPerson->kids[i]); } } return newPerson; }
内容的提问来源于stack exchange,提问作者A. Lev
相关产品推荐
相关产品推荐

