2015-10-15 43 views
1

我是C新手,无所适从。几个小时我一直在撞墙。将节点添加到链接列表时发生堆损坏

我创建了两个struct s来保存我的链表节点。第一个,struct movie显然拥有电影。第二个struct 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

更新异常:

通过我的代码精心挑选后,我发现了一个明显的错误。当传递大于几个字符的内容时,程序会崩溃。当我声明传递给add_actor函数的指针变量movie_nameactor_name时,我没有为较大的名称分配足够的空间。

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

就目前来看,这是很多需要经历的代码。你可能[编辑]并将其折叠到[MCVE](http://stackoverflow.com/help/mcve)?谢谢! – CodeMouse92

+0

编辑完成,谢谢 – corporateWhore

+4

建议阅读[如何调试小程序](http://ericlippert.com/2014/03/05/how-to-debug-small-programs/)(再次)。创建此MCVE将导致在80%的案例中自己发现错误,并在剩下的情况下帮助其他人帮助:) –

回答

3

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

但无论如何,我会提到这些错误...

一:

当你到了这一点:

tmpActor = tmp->actors; 

tmp保证是NULL从你的第一个循环。
你可能是指

tmpActor = tmpList->actors; 

二:

当你在这里:

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

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

我想你应该

tmpList->actors = newActor; 

三和更换

tmpActor = newActor; 

:不投的malloc结果。

+0

'tmpActor = tmp-> actors;'一定是'tmpActor = tmpList-> actors;'只要做了这样的改变,我就能够创建三部电影,并将三个演员添加到两部电影中的每一部,并且[valgrind '](http://valgrind.org/)只会抱怨(相当合理)泄漏的内存。很显然,我必须编写一个'add_movie()'函数,并且我设法充分发挥了它的作用,不会导致问题。我没有编写代码来打印数据,所以可能还有其他问题我没有找到。 –

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; 

} 
+0

我只是重新格式化您的代码,使其更清晰和维护,现在没有错误(认为释放内存alocated) – milevyo

+0

看起来不错。我保存了你的代码,因为它更清洁!谢谢回复。 – corporateWhore

+0

虽然ACTOR演员;没有使用,但错过录音应该是ACTOR *演员; – milevyo