2016-09-01 43 views
1

私は単純なキューをC言語で実装していますが、デキューした後にQ.frontにアクセスしようとすると、セグメンテーション違反が発生します(例えばint main()を参照してください)。 Cのこのキューインプリメンテーションでセグメンテーションフォルトが発生するのはなぜですか?

は、より正確には、問題が発生したときにI -

  1. エンキュー単一の要素。
  2. デキューします。
  3. 1つまたは複数の要素をエンキューします。

    1. エンキュー複数の要素 - プログラムがセグメンテーションフォールトまたは任意のエラーIを与えるものではありませんしかし

    Q.front

  4. にアクセスしてみてください。
  5. 一度だけデキューします。
  6. 多くの要素をエンキューします(オプション)
  7. アクセスQ.front正常に。

だからこれは私の完全なプログラムです -

#include <stdio.h> 
#include <stdlib.h> //for malloc 

struct qnode 
{ 
    int r; 
    struct qnode *link; 
}; 

typedef struct qnode qNode; 

typedef struct 
{ 
    qNode *front; 
    qNode *rear; 
    int qsize; 
}QUEUE; 

QUEUE initializeQueue(void) 
{ 
    QUEUE q; 
    q.front = NULL; 
    q.rear = NULL; 
    q.qsize = 0; 
    return q; 
} 


qNode *createQueueNode(int e) 
{ 
    qNode *temp; 
    temp = (qNode *) malloc(sizeof(qNode)); 
    if(temp == NULL) 
    { 
     printf("INSUFFICIENT MEMORY\n"); 
     exit(0); 
    } 
    temp->r = e; 
    temp->link = NULL; 
    return temp; 
} 
QUEUE enqueue(QUEUE q, int e) 
{ 
    if(q.rear == NULL) 
    { 
     q.rear = createQueueNode(e); 
     q.front = q.rear; 
     q.qsize++; 
    } 
    else 
    { 
     q.rear->link = createQueueNode(e); 
     q.rear = q.rear->link; 
     q.qsize++; 
    } 
    return q; 
} 

QUEUE dequeue(QUEUE q) 
{ 
    qNode *temp; 
    if(q.front == NULL) 
    { 
     printf("queue is empty\n"); 
     exit(0); 
    } 
    else 
    { 
     temp = q.front; 
     q.front = q.front->link; 
     free(temp); 
    } 

    q.qsize--; 
    return q; 
} 



int main(){ 

    QUEUE Q = initializeQueue(); 
    Q = enqueue(Q, 2); 
    printf("%d\n",Q.front->r); 
    Q = dequeue(Q); 
    Q = enqueue(Q,4); 
    printf("%d\n",Q.front->r); // This line is giving segmentation fault 

    return 0; 
} 

答えて

1

デキューは、q.rearにq.frontをNULLに設定します(以前はcreateQueueNodeでNULLに設定されていたq.front-> linkから)。q.rearにゴミ箱ポインタ(free()のメモリ)を残します。 q.rearはNULLではないので、enqueueのif文の2番目のブロックは、2番目のenqueue呼び出しで実行されます。 free()のメモリ(q.rear-> link)に書き込んだ後、q.rearに逆参照します。私はそれが実際にフリーメモリに書き込むことで実際にはクラッシュしないことに驚いています。クイックフィックスは、キューが空の場合、デキューでq.rearをNULLに設定することです。デキューが空のキューで実行されないようにサニティチェックも追加する必要があります。

また、ホットポテトのようにその構造を渡すという興味深い方法があります。なぜそれを参照で渡し、それを返すのではなくその場で修正するのですか?

1
Program terminated with signal 11, Segmentation fault. 
#0 0x0000000000400859 in main() at ./2.c:87 
87   printf("%d\n",Q.front->r); // This line is giving segmentation fault 
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.80.el6.x86_64 
(gdb) p Q 
$1 = {front = 0x0, rear = 0x1636010, qsize = 1} 

フロントがnullで、あなたはそれにアクセスします。 あなたのプログラムで何がうまくいかないかを見るには、gdbのようなデバッガが必要です。

+0

デキュー操作後にもう1つの要素をエンキューした場合、どのようにnullになりますか? –

+0

キューポイントはその新しいエンキューされた要素を指していませんか? –

関連する問題