2017-01-25 9 views
0

私は二重リンクリストのためのCプログラムを書いています。以下のコードは、main関数とinsert関数を含んでいます。それが正常にコンパイルされgcc cfile.cと上記のコードをコンパイルするこのプログラムでランタイムエラーが発生するのはなぜですか?

cfile.c

/* 
    In the following code doubly linked list is implemented 
*/ 

//header files 
#include <stdio.h> 
#include <stdlib.h> 

//create structure for node 
struct node{ 
    int info; 
    struct node *LChild; 
    struct node *RChild; 
}*start; 

typedef struct node *NODE; 

//function to insert data in the list 
void insert(){ 
    int data; 
    NODE q, temp; 
    temp = (NODE)malloc(sizeof(struct node)); 
    if(temp){ 
     printf("\nEnter the data to be inserted in the list: "); 
     scanf("%d", &data); 
     temp->info = data; 
     temp->RChild = NULL; 
    } 
    else{ 
     printf("Out of memory."); 
     return; 
    } 
    if(start == NULL){ 
     temp->LChild = NULL; 
     start->LChild = temp; 
     start = temp; 
    } 
    else{ 
     q = start; 
     while(q->RChild != NULL){ 
      q = q->RChild; 
     } 
     q->RChild = temp; 
     temp->LChild = q; 
    } 
    return; 
} 

//function to insert at the begining 
void insert_at_beg(){ 
    int data; 
    NODE temp; 
    temp = (NODE)malloc(sizeof(struct node)); 
    if(temp){ 
     printf("\nEnter the data to be inserted at the beginning of the list: "); 
     scanf("%d", &data); 
     temp->info = data; 
     temp->LChild = NULL; 
     temp->RChild = start; 
     start->LChild = temp; 
     start = temp; 
    } 
    else{ 
     printf("Out of memory."); 
    } 
    return; 
} 

//function to insert after a position 
void insert_after_pos(){ 
    int data, pos; 
    NODE temp, q; 
    printf("\nEnter the position after which data will be inserted: "); 
    scanf("%d", &pos); 
    q = start; 
    for(int i = 0; i < pos-1; i++){ 
     q = q->RChild; 
     if(q == NULL){ 
      printf("There are less than %d position.", pos); 
      return; 
     } 
    } 
    temp = (NODE)malloc(sizeof(struct node)); 
    if(temp){ 
     printf("\nEnter the data to be inserted after the %d position: ", pos); 
     scanf("%d", &data); 
     temp->info = data; 
     q->RChild->LChild = temp; 
     temp->RChild = q->RChild; 
     temp->LChild = q; 
     q->RChild = temp; 
    } 
    return; 
} 

//function to delete the node 
void delete(){ 
    NODE temp, q; 
    int num; 
    printf("\nEnter the data to be deleted: "); 
    scanf("%d", &num); 
    if(start->info == num){ 
     temp = start; 
     start = start->RChild; 
     start->LChild = NULL; 
     free(temp); 
     return; 
    } 
    q = start; 
    while(q->RChild->RChild != NULL){ 
     if(q->RChild->info == num){ 
      temp = q->RChild; 
      q->RChild = temp->RChild; 
      temp->RChild->LChild = q; 
      free(temp); 
      return; 
     } 
     q = q->RChild; 
    } 
    if(q->RChild->info == num){ 
     temp = q->RChild; 
     free(temp); 
     q->RChild = NULL; 
     return; 
    } 
    printf("\nElement %d is not found on this list.", num); 
    return; 
} 

//function to display the list 
void display(){ 
    NODE q; 
    if(start == NULL){ 
     printf("\nList is empty."); 
     return; 
    } 
    q = start; 
    while(q != NULL){ 
     printf("%d ", q->info); 
     q = q->RChild; 
    } 
    return; 
} 

//function to reverse the list 
void reverse(){ 
    NODE p1, p2; 
    p1 = start; 
    p2 = p1->RChild; 
    p1->RChild = NULL; 
    p1->LChild = p2; 
    while(p2 != NULL){ 
     p2->LChild = p2->RChild; 
     p2->RChild = p1; 
     p1 = p2; 
     p2 = p2->LChild; 
    } 
    start = p1; 
    return; 
} 

int main(){ 
    int choice; 
    char ch; 
    start = NULL; 
    printf("Menu for doubly linked list"); 
    do{ 
     printf("\n1.Insert\n2.Insert at beginning\n3.Insert after position\n4.Display\n5.Delete\n6.Reverse\n7.Exit\nEnter your choice: "); 
     scanf("%d", &choice); 
     switch(choice){ 
      case 1: insert(); 
        break; 
      case 2: insert_at_beg(); 
        break; 
      case 3: insert_after_pos(); 
        break; 
      case 4: display(); 
        break; 
      case 5: delete(); 
        break; 
      case 6: reverse(); 
        break; 
      case 7: exit(0); 
        break; 
      default: printf("Invalid choice!"); 
     } 
     printf("\nDo you want to continue ? "); 
     scanf(" %c", &ch); 
    }while(ch == 'y' || ch == 'Y'); 
    return 0; 
} 

。 しかし、実行時エラーが発生しています。 gdbでデバッグすると、28行目に何らかのエラーがあることがわかりました。残念ながら、何がエラーなのか分かりません。それは表示しています

私は逆参照ポインタで何かをしなければならないことを知っています。

なぜですか?何がこのコードで間違って、私はinsert関数を呼び出す前にstart = NULLをやった。

は、ここで私はSTACKDUMPについて何も知らないSTACKDUMP

Exception: STATUS_ACCESS_VIOLATION at rip=0010040116A 
rax=0000000000000000 rbx=00000000FFFFCC40 rcx=0000000600018040 
rdx=0000000600028460 rsi=00000006000283B0 rdi=0000000000000000 
r8 =00000000FFFFB5FC r9 =000000018013E150 r10=0000000100000000 
r11=000000010040111C r12=00000000FFFFCC61 r13=0000000000000000 
r14=00000000FFFFCC61 r15=000000018021AE83 
rbp=00000000FFFFCBC0 rsp=00000000FFFFCB80 
program=E:\Learning\Languages\C\a.exe, pid 8612, thread main 
cs=0033 ds=002B es=002B fs=0053 gs=002B ss=002B 
Stack trace: 
Frame  Function Args 
000FFFFCBC0 0010040116A (000FFFFCC61, 00000000000, 000FFFFCC61, 000FFFFCCC0) 
000FFFFCBF0 001004011E6 (00000000020, FF0700010302FF00, 00180047891, 00000000000) 
000FFFFCCC0 00180047902 (00000000000, 00000000000, 00000000000, 00000000000) 
00000000000 00180045693 (00000000000, 00000000000, 00000000000, 00000000000) 
000FFFFFFF0 00180045744 (00000000000, 00000000000, 00000000000, 00000000000) 
End of stack trace 

です。だから私はそれを理解することができません。

gccのバージョン:5.4.0 gdbのバージョン:このブロックで7.10.1

答えて

5

if(start == NULL){ 
    temp->LChild = NULL; 
    start->LChild = temp; // <<< `start` is NULL here !!! 
    start = temp; 
} 

それはまだNULLているときに、したがって、間接参照startしようとしていますseg fault。

+0

どのような修正が必要ですか? – user123456987

+1

これは、この時点でコードを使って達成しようとしていることに依存しています。誰もあなたの意図を本当に推測することはできませんが、ノードを挿入しようとしていて、ロジックが混乱しているようです。 –

+0

はいノードをリストに挿入しようとしています。 – user123456987

1

"SIGSEGV、Segmentation fault"は、無効なポインタアクセスや、他のプログラミング言語で知られているシンプルなNULLポインタ例外のようなものです。

したがって、ヌルポインタのメンバーには明らかにアクセスできません。

1

コードの問題点は、(いくつかの場所で)ポインタがNULLではないことを確認せずに使用することです。このようなコード:あなたはNULLポインタを参照解除されているよう

NODE start = NULL; 
start->LChild = ....whatever....; 

は、ランタイムエラーが発生します。

ポインタを扱うときに非常に重要な教訓は次のとおりです。

は常にポインタが@PaulRからの答えはすでにあなたに1つの場所を伝え、それを

を逆参照する前に、有効な何かを指していることを確認してくださいあなたのコードは間違っていますが...もっとあります。インサートで

()(既に@PaulRにより述べたように)insert_at_begにおいて

if(start == NULL){ 
    temp->LChild = NULL; 
    start->LChild = temp; // ups, start is NULL 
          // You probably just need to delete this line 
          // as all you want is to make start equal to temp 
    start = temp; 
} 

()insert_after_posにおいて

temp->RChild = start; 
    start->LChild = temp; // ups, start may be NULL 
          // you need to add a check here like 
          // if (start != NULL) start->LChild = temp; 
    start = temp; 

()

q = start;    // start may be NULL 
for(int i = 0; i < pos-1; i++){ 
    q = q->RChild;  // so here you may be using a NULL pointer 

ループに入る前に、startNULLであるかどうかチェックし、そうであれば返す必要があります。削除で

()の逆で

if(start->info == num){ // ups, start may be NULL 
         // Add a check 

()

p1 = start;  // start may be NULL 
p2 = p1->RChild; // ups.... 
        // Add a check 

いくつかの他のコメント:

1)名前NODEにポインタをtypedef'ingでありますあなたのコードの他の読者にとっては非常に不明です。避けてください!または、少なくともポインタがポインタであることを明確に示す名前を使用します。 NODE_P

2)必ずscanfが返す値を確認してください。例:

if (scanf("%d", &num) != 1) 
{ 
    // Input error 
    .... 
    Add error handling here 
    .... 
} 
関連する問題