2015-10-15 89 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