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

时间:2018-01-05 23:14:40

标签: c initialization malloc

编辑:已解决。谢谢!

我有一个函数返回指向我构建的结构的指针。我有一个问题,我的代码在调试模式下运行,但在正常模式下崩溃,只有在我尝试将孩子添加到此人时崩溃才会崩溃: 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;
}

2 个答案:

答案 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;
    }

    ...
}