编辑:已解决。谢谢!
我有一个函数返回指向我构建的结构的指针。我有一个问题,我的代码在调试模式下运行,但在正常模式下崩溃,只有在我尝试将孩子添加到此人时崩溃才会崩溃: 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("%s\n",tempName);
strcpy(newPerson->kids[i],tempName);
printf("%s\n",newPerson->kids[i]);
}
}
return newPerson;
}
答案 0 :(得分:2)
此代码没有为复制的字符串的终止<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="keep-open btn-group" title="Add Listener">
<ul class="dropdown-menu" role="menu">
<li><label><input type="checkbox" data-field="1" value="0" checked="checked"> Category</label></li>
<li><label><input type="checkbox" data-field="2" value="1" checked="checked"> Item 1</label></li>
<li><label><input type="checkbox" data-field="3" value="2" checked="checked"> Item 2</label></li>
<li><label><input type="checkbox" data-field="4" value="3" checked="checked"> Item 3</label></li>
</ul>
</div>
<label>
<input type="checkbox" checked="checked"> Not this checkbox
<label>
<div>
<input type="button" id="add" value="add" />
</div>
字符分配足够的内存:
NUL
字符串包含newPerson->name=(char*)malloc(strlen(tempName)*sizeof(char));
strlen()
个值,加上终止char
。
将该行更改为
NUL
请注意,根据定义,newPerson->name=malloc(1 + strlen(tempName));
是一个。而且您不需要在C中投射sizeof(char)
的结果。
或者,如果它可用,您只需使用strdup()
即可。它不是标准的C,因为它违反了不成文的规则&#34;关于内存的隐式分配需要malloc()
&#39; d,但它有效。
另外,正如评论中所述:
free()
错误,因为它分配了大小为newPerson=(Person*)malloc(sizeof(newPerson));
的内存块,一个指针,而不是newPerson
。将其更改为
struct
答案 1 :(得分:1)
请不要投射malloc
以及其家人的其他功能。见Do I cast the result of 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));
没有分配足够的空间,很容易错过*
中的size
calloc
的论据。
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;
}
...
}