将节点添加到链接列表时堆积损坏

时间:2015-10-15 23:33:11

标签: c pointers linked-list nodes

我是C的新手并且不知所措。我一直在墙上撞了几个小时。

我创建了两个struct来保存我的链表节点。第一个,struct movie显然拥有电影。第二个struct actor是将actor节点添加到电影节点。

struct movie {
    struct movie* next;
    struct actor* actors;
    char name[100];
    int rating;
    genre type;
} *list = NULL;


// contains actor information
struct actor {
    struct actor* next;
    char name[100];
};

当我尝试将actor添加到movie时会出现问题。

int add_actor(char* movie_name, char* actor_name)
{
    struct movie *tmp = list, *tmpList = NULL;
    struct actor *tmpActor = NULL, *current = NULL;

    //check if movie name exists in list
    while (tmp != NULL) {
        if (strcmp(tmp->name, movie_name) == 0) {
            tmpList = tmp;
        }
        tmp = tmp->next;
    }                                                                       //make sure newActor->next is pointing to the correct place
    if (tmpList == NULL) { return 0; } //if movie in not in list, return 0

    //The problem occurs most often at this line, with the exception below.
    //Exception thrown at 0x77433500 (ntdll.dll) in hw7.exe: 0xC0000005: Access violation reading location 0x006F4E42
    struct actor *newActor = (struct actor*)malloc(sizeof(struct actor));//create new actor node

    if (tmpList->actors == NULL){ //if the movie has no actors in list
        tmpList->actors = newActor;
        strcpy(newActor->name, actor_name);
        newActor->next = NULL;
        return 1;
    }
    else { //check if actor name already exists in list
        while (tmpActor != NULL) {
            if (strcmp(tmpActor->name, actor_name) == 0) {
                return -1; //if actor already exists return -1
            }
            tmpActor = tmpActor->next;
        }

        tmpActor = tmp->actors;

        //insert at beginning of list
        if (strcmp(actor_name, tmpActor->name) >= 0) {
            newActor->next = tmpActor;
            tmpActor = newActor;
            return 1;
        }
        //insert actor in arbitrary position
        while (tmpActor != NULL && strcmp(actor_name, tmpActor->name)<0) {
            current = tmpActor;
            tmpActor = tmpActor->next;
        }
        newActor->next = current->next;
        strcpy(newActor->name, actor_name);
        current->next = newActor;
        return 1;
    }
}

充其量我能够将两个演员添加到两部不同的电影中。问题总是出现在第三个条目上。

这是抛出的异常 enter image description here

更新:

经过仔细挑选我的代码后,我发现了一个明显的错误。传递任何大于几个字符的程序时程序会崩溃。当我声明传递给movie_name函数的actor_nameadd_actor指针变量时,我没有为更大的名称分配足够的空间。

char* movie_name = (char*)malloc(sizeof(char*));
char* actor_name = (char*)malloc(sizeof(char*));

更改为:

char* movie_name = (char*)malloc(5000*sizeof(char*));
char* actor_name = (char*)malloc(5000*sizeof(char*));

我可以在不崩溃的情况下添加电影和演员。

2 个答案:

答案 0 :(得分:3)

我看到两个错误 但是,它们中的任何一个都不太可能是崩溃的根源,因为在您的测试用例中都没有执行。 (除非你在每部电影中添加两个演员 - 这个问题很难解释)。
最终的原因可能在于添加电影或其他地方的功能 当堆已经损坏时,您可以肯定地说它是在程序启动和崩溃之间的某个时刻发生的。

但我还是会提到这些错误......

一:

当你达到这一点时:

tmpActor = tmp->actors;
第一次循环保证

tmpNULL 你可能意味着

tmpActor = tmpList->actors;

二:

当你到达这里时:

    //insert at beginning of list
    if (strcmp(actor_name, tmpActor->name) >= 0) {
        newActor->next = tmpActor;
        tmpActor = newActor;
        return 1;
    }

您将新演员分配到tmpActor,这是一个局部变量。

我认为你应该替换

tmpActor = newActor;

tmpList->actors = newActor;

三:不要投出malloc的结果。

答案 1 :(得分:0)

#include <string.h>
#include <stdio.h>
#include <stdlib.h>


typedef struct movie MOVIE;
typedef struct actor ACTOR;



typedef enum {
    Action,
    Documentary,
    Animation /*etc ...*/
}genre;
struct movie{ 
    MOVIE* next; 
    ACTOR* actors; 
    char name[100]; 
    int rating;    
    genre type; 
} ;
// contains actor information

struct actor { 
    ACTOR* next; 
    char name[100]; 
};

MOVIE *list = NULL;



/*_______________________________________________________
*/
MOVIE *List_FindMovie(const char *movie_name){
    MOVIE *tmp = list; 

    while (tmp != NULL) { 
        if (_stricmp(tmp->name, movie_name) == 0) {
            return tmp; 
        }        
        tmp = tmp->next; 
    }
    return NULL;
}

/*_______________________________________________________
*/
ACTOR *Movie_FindActor(MOVIE *movie,const char*actor_name){
    ACTOR  *tmpActor=movie->actors;
    while(tmpActor){
        if(_stricmp(tmpActor->name,actor_name)==0)
            return tmpActor;
        tmpActor=tmpActor->next;
    }
    return NULL;
}
 /*_______________________________________________________
*/
int List_ActorInfo(const char *actor_name){
    MOVIE *tmp = list; 
    int nmovies=0;
    printf("Actor '%s' participations:\n",actor_name);
    while (tmp != NULL) { 
        if(Movie_FindActor(tmp,actor_name)){
            nmovies++;
            printf("\t- %s\n",tmp->name);
        }
        tmp = tmp->next; 
    }

    if(nmovies)
        printf("\t  Total: %d movies\n\n",nmovies);
    else
        printf("\t  None\n\n");
    return nmovies;
}   
/*_______________________________________________________
*/
ACTOR *NewActor(const char*actor_name){
    ACTOR *NewActor=calloc(1,sizeof(ACTOR));
    strcpy(NewActor->name,actor_name);
    return NewActor;
}
/*_______________________________________________________
*/
ACTOR *Movie_AddActor(MOVIE *movie,ACTOR *NewActor){
    if(!movie->actors){
        movie->actors=NewActor;
    }else{
        ACTOR *prevActor=NULL,*current=movie->actors;
        while(_stricmp(current->name,NewActor->name)<0){

            prevActor=current;
            current=current->next;
            if(!current)break;
        }
           NewActor->next=current;
            if(prevActor)
                prevActor->next=NewActor;
            else
                movie->actors=NewActor;

    }
    return NewActor;
}


/*_______________________________________________________
*/
MOVIE * List_AddMovie(const char *movie_name,genre type){
    MOVIE *movie,*tmpMovie;
    if(movie=List_FindMovie(movie_name)) return 0;

    movie=calloc(1,sizeof(MOVIE));
    strcpy(movie->name,movie_name);
    movie->type=type;
    if(!list)
        list=movie;
    else{
        tmpMovie=list;
        while(tmpMovie->next)
            tmpMovie=tmpMovie->next;
        tmpMovie->next=movie;
    }
    return movie;
}
/*_______________________________________________________
*/
void Movie_PrintActors(MOVIE *movie){
    ACTOR *actor=movie->actors;
    printf("Actors in Movie '%s':\n",movie->name);
    while(actor){
        printf("\t%s\n",actor->name);
        actor=actor->next;
    }
    printf("\n");

    return;
}
/*_______________________________________________________
*/

int main(){
    MOVIE *mv;


    List_AddMovie("Dogs",0);
    mv=List_AddMovie("Dragons",0);


    if(!mv){
        printf("failed to add movie\n");
        exit(-1);
    }
    Movie_AddActor(mv,NewActor("Z"));
    Movie_AddActor(mv,NewActor("C"));
    Movie_AddActor(mv,NewActor("A"));
    Movie_AddActor(mv,NewActor("Cat8"));
    Movie_PrintActors(mv);

    mv=List_FindMovie("Dogs");
    Movie_AddActor(mv,NewActor("Dog1"));
    Movie_AddActor(mv,NewActor("Dog3"));
    Movie_AddActor(mv,NewActor("Dog6"));
    Movie_AddActor(mv,NewActor("Cat8"));

    Movie_PrintActors(mv);

    List_ActorInfo("Bruce Lee");
    List_ActorInfo("Cat8");
    return 0;

}