2017-03-08 4 views
2

5つのアイテムについてmallocされている間に7つのアイテムをプッシュしていますが、セグメンテーションは起こっていません。私は何が欠けていますか?私は、これは、ポインタが配列の境界を越えて移動させるだろうと思ったとCがハンドリングされたキューにアイテムをあまりにも多く押し込んでいる - なぜこれはセグメンテーションではありませんか?

#include "stdlib.h" 
#include "stdio.h" 
#include "assert.h" 

typedef struct { 
    int *space; 
    int size; 
    int *start; 
    int *end; 
} queue_t; 

typedef char BOOL; 

#define TRUE 1 
#define FALSE 0 

void queue_print(queue_t *queue) { 

    for (int *cur = queue->start; cur < queue->end; cur++) { 
     printf("%i,", *cur); 
    } 

    printf("\n"); 
} 

void queue_init(queue_t **queue, int size) { 
    (*queue) = (queue_t*) malloc(sizeof(queue_t)); 
    (*queue)->space = (int*) malloc(sizeof(int) * size); 
    (*queue)->size = size; 
    (*queue)->start = (*queue)->space; 
    (*queue)->end = (*queue)->space; 
} 

void queue_push(queue_t *queue, int elem) { 
    *(queue->end) = elem; 
    queue->end++; 
} 

int queue_pop(queue_t *queue) { 
    int ret = *(queue->start); 
    queue->start++; 
    return ret; 
} 

int main(int argc, char const *argv[]) 
{ 
    queue_t *queue; 
    queue_init(&queue, 5); 
    queue_print(queue); 
    queue_push(queue, 1); 
    queue_print(queue); 
    queue_push(queue, 2); 
    queue_print(queue); 
    queue_push(queue, 3); 
    queue_print(queue); 
    queue_push(queue, 4); 
    queue_print(queue); 
    queue_push(queue, 5); 
    queue_print(queue); 
    queue_push(queue, 6); 
    queue_print(queue); 
    queue_push(queue, 7); 
    queue_print(queue); 
    printf("%i\n", queue->size); 
    queue->space[123] = 4; 
    return 0; 
} 

出力は次のようになります。

1, 
1,2, 
1,2,3, 
1,2,3,4, 
1,2,3,4,5, 
1,2,3,4,5,6, 
1,2,3,4,5,6,7, 
+0

よく、次のmallocにはおそらく問題があります。 :-)メインでコードを複製し、別のキューを作成しようとします。 – Arash

+0

興味深い。 clangスタティックアナライザは、2番目のキューのメモリリークを警告します。 –

答えて

0

Cが範囲外にチェックしませんアクセスが、あなたのプログラムは、ヒープが破損し、あなたはmalloc()をもう一度呼びますが、おそらくsegfaultがあります。

+0

それは面白いです。あなたはそれについてもっと説明したり、このケースを研究するために使うことができる何らかの情報源を指していますか?どうもありがとう! –

+0

これは役立ちます:http://stackoverflow.com/questions/1957099/how-do-free-and-malloc-work-in-c – DyZ

+0

_おそらく原因。確率の側面に対処するための答えを変更しました。 – DyZ

0

queue_initを呼び出して5つの整数を格納する領域を割り当てます。

(gdb) p *queue 

あなたはスタートメンバーのメモリアドレスが表示されます:あなたはqueue->startの場所でメモリをGDBでコードを実行し、調べると次のように表示されます。 5バイト目はどちらか未割り当てか、以前に割り当てられた何かに所属した後、

0x602450: 0 0 0 0 
0x602460: 0 0 134049 0 

がすべて:

(gdb) x/8 0x602450 

gdbのようなものを出力します。このような何かが、調べてメモリコマンドでそのアドレスを使用してください。

(gdb) x/8 0x602450 
0x602450: 1 2 3 4 
0x602460: 5 6 7 0 

ので、ランタイムが割り当てられていないか、以前に割り当てられたメモリを上書きするのを防ぐことはできません:あなたの第七の呼び出しがqueue_pushし、そして再度メモリを調べた後、あなたはこのような何かを参照してくださいね。しかし、実行時に問題を引き起こす可能性がある重要な問題や、プロセス内の他のスレッドを記述している可能性があります。

+1

非常に良い説明!だから私は何が起こっているのか理解しています。しかし、もし私が配列の終わりを超えて書くことができれば、segfaultは何ですか? http://www.cprogramming.com/debugging/segfaults.htmlから私は「セグメンテーションフォルトにつながる4つの一般的な間違いがあります:NULLの参照解除、初期化されていないポインタの逆参照、解放された(または削除された)ポインタの逆参照、 (関数で宣言された配列の場合)スコープを超えてしまい、配列の終わりを書き去ってしまいます。 –

+1

配列の終わりを書くことは必ずしもセグメンテーションフォールトを引き起こすとは限りません。それはあなたが書き込むものによって異なります。メモリマネージャによっては自動的に検出され、ランタイムエラーが発生します。また、メモリを解放すると、エラーが発生する可能性が最も高くなります。だから、おそらく 'main'の' return'の前に次の2行を追加してください:\t 'free(queue-> space);空き(キュー); ' – bruceg

+2

はい。これはメモリアロケータから直接エラーをスローします。どれくらい楽しいですか? TKS! –

関連する問題