malloc 问题 - C 程序在调试中运行,但在正常运行时崩溃



编辑:已解决。谢谢!

我有一个函数,它返回指向我构建的结构的指针。我有一个问题,我的代码在调试模式下运行但在正常模式下崩溃,只有当我尝试将孩子添加到该人时,它才会崩溃 - 从: if (kidsNumber>0){我很确定这是初始化问题,但我找不到在哪里,我卡住了。我试图放置标志和断点,但没有任何帮助。谢谢!

Person* CreatePerson(){
Person* newPerson;
newPerson=(Person*)malloc(sizeof(newPerson));
if (newPerson==NULL){
return NULL;
}
InitPersonValues(newPerson);
char tempName[MAX_NAME];
int id;
int kidsNumber;
printf("Name:n");
scanf("%s",tempName);
newPerson->name=(char*)malloc(1 + strlen(tempName));
if (newPerson->name == NULL){
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){
return NULL;
}
int i=0;
for (i=0;i<kidsNumber;i++){
strcpy(tempName,"");
printf("Kid #%d name:n",i+1);
scanf("%s",tempName);
newPerson->kids[i]=malloc(strlen(tempName)+1);
if (newPerson->kids[i]==NULL){
return NULL;
}
// printf("%sn",tempName);
strcpy(newPerson->kids[i],tempName);
printf("%sn",newPerson->kids[i]);
}
}
return newPerson;
}

此代码没有为复制的字符串的终止NUL字符分配足够的内存:

newPerson->name=(char*)malloc(strlen(tempName)*sizeof(char));

字符串包含strlen()char值以及终止NUL

将该行更改为

newPerson->name=malloc(1 + strlen(tempName));

请注意,根据定义,sizeof(char)是一个。 而且您不需要在 C 中转换malloc()的结果。

或者,如果可用,您可以简单地使用strdup(). 它不是标准的 C,因为它违反了关于需要free()的内存隐式分配的不成文"规则",但它有效。

另外,如评论中所述:

newPerson=(Person*)malloc(sizeof(newPerson));

是错误的,因为它分配了一个大小为newPerson的内存块,一个指针,而不是struct。 将其更改为

newPerson=malloc(sizeof(*newPerson));

请不要投malloc及其家族的其他功能。请参阅我是否投射 malloc 的结果?

使用malloc的最佳方式是:

int *var = malloc(size * sizeof *var);

避免在参数中使用sizeof(int*)。很容易犯错误, 忘记*等。如果以后更改数据类型,则还必须更改参数。sizeof *var每次都返回正确的大小,无论类型如何(只要var是指针)。

calloc也是如此

int *var = calloc(size, sizeof *var);

你看到问题了吗?

newPerson->kids=(char**)calloc(kidsNumber,sizeof(char));

没有分配足够的空间,很容易错过*sizecalloc的论据 .

newPerson->kids=calloc(kidsNumber, sizeof *newPerson->kids);

返回确切的内存量。

newPerson->name=(char*)malloc(strlen(tempName)*sizeof(char));

不要投掷,不要使用sizeof(char)

newPerson->name=malloc(strlen(tempName) + 1); // for strings
// or if you want to be 100% correct, but that's overkill
// since you know that you are requesting space for a C-String
newPerson->name=malloc((strlen(tempName) + 1) * sizeof *newPerson->name);

如果可能,如果要克隆字符串,也请使用strdup。如果你是 环境没有strdup,自己写一个:

char *strdup(const char *s)
{
char *str = malloc(strlen(s) + 1);
if(str == NULL)
return NULL;
strcpy(str, s);
return str;
}

这将使您的代码更具可读性。


编辑

重读你的问题后,我注意到了一件小事。

如果您注意到在创建新Person时某些内容失败,请不要只是 返回NULL并完成它。释放已分配的内存。

我会做这样的事情:

void DestroyPerson(Person *person)
{
if(person == NULL)
return;
if(person->kids)
{
int i;
for(i = 0; i < person->numOfKids; ++i)
free(person->kids[i]);
free(person->kids);
}
free(person);
}
// returns 1 on success, 0 otherwise
int InitPerson(Person *person)
{
memset(person, 0, sizeof *person);
// some other initializations
...
return 1;
}
Person* CreatePerson() {
Person *newPerson;
newPerson=malloc(sizeof *newPerson);
if (newPerson==NULL){
return NULL;
}
// initializing kids
if(!InitPerson(person))
{
DestroyPerson(person);
return NULL;
}
...
if(some_error_detected)
{
DestroyPerson(newPerson);
return NULL;
}
...
}

最新更新