2012-04-06 7 views
-4

以下は'E'が入力されるまで未知数の単語を入力するコードです。入力したすべての単語を停止して印刷する必要があります。ただし、このプログラムを実行すると、セグメント化エラーが発生します。私は持ってはいけないメモリにアクセスしましたか?は、配列ワードを出力する際に​​セグメンテーションエラーを受け取ります

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

#define CAPACITY 10 
#define NUM_OF_WORDS 10 
int main(void) 
{ 
    int num_words = 10; 
    char *word= malloc(CAPACITY*sizeof(char)); 
    char **w=(char **) malloc(num_words*sizeof(char)); 
    int i; 
    for(i = 0 ; scanf("%s", word)==1; ++i) 
    { 
     if(*word == 'E') 
      break; 
     if(i == num_words-1) 
      w = (char **)realloc(w, (num_words *=2) * sizeof(char)); 
     w[i] =(char *) malloc(strlen(word)+1 * sizeof(char)); 
     strcpy(w[i], word); 
    } 
    int x = 0; 
    for(x = 0 ; x<num_words ; x++) 
     printf("%s", w[x]); 
    return 0; 
} 
+1

は、それがどのような入力をクラッシュさせ、そして何行に:私はあなたが使用したほうが良いと思いますか? –

+0

@JohnZwinckが正しいです。 "私はセグメンテーションエラーを受け取りました"あなたがそれをどのようにテストしたか分からなければ、あまり役に立ちませんか?すぐにクラッシュしますか?特定の入力後?デバッガで実行しましたか? – abelenky

+0

私はデータの入力を止め、プログラムが何かを印刷するはずだったとき、私はsegを受け取りました。 'printf' for for'ループのエラー –

答えて

0

あなた変数num_wordswアレイの現在の最大サイズを保持し、それはアレイ内の実際の単語の数と同じではありません。

wアレイをループすると、あまりにも多くの項目をループしています - wのいくつかの要素には有効な文字列がありません。それらを印刷しようとするとsegfaultが発生します。

+0

はい、私もそれが問題だと思います。それで、それらを印刷するためのより良い解決策がありますか? –

+0

@ twain249 - mallocされたバッファに何が含まれているかによってsegfaultが発生する場合もあれば、そうでない場合もあります。 mallocはメモリがゼロになることを保証しません。 – shf301

+0

ああ、愚かな私、私はちょうどnum_wordsの代わりに私を使用することができます –

1

あなたの初期割当てコード読み取り:

char *word = malloc(CAPACITY*sizeof(char)); 
char **w = (char **) malloc(num_words*sizeof(char)); 

は、これらの両方は、メモリの10のバイトを割り当てます。

char **w = (char **) malloc(num_words*sizeof(char *)); 

か::あなたのもう一つは読むべき

char **w = malloc(num_words*sizeof(*w)); 

これらの両方の(元のコードとして8倍のメモリであるかもしれない)10のポインタのための十分なメモリを割り当てます。 2番目は間違いなく良いスタイルです。最初のものは間違いなく古典的なスタイルです。 Cでは、malloc()のキャストは必要ありません。 C++では、そうです。

これは全体の問題ではないかもしれません。それはほぼ確実に寄与する要素です。

また、メモリ割り当てもチェックしていません。それはお勧めできません。常にチェックしてください。


このコード:

if (i == num_words-1) 
    w = (char **)realloc(w, (num_words *=2) * sizeof(char)); 

は、2つのアカウント(プラス以前に診断問題の繰り返し)に火で遊んでいる:引数リスト内の

  1. 割り当てがあります。一般的には良い考えであるとは考えられていません。私はその場所にコードを書いていないでしょうし、私はそれを含むレビューをするように求められたコードを送り返します。技術的に間違っているわけではありません。それが動作します。しかし、それは後に来るメンテナンスプログラマーの人生を楽にしません。

  2. wのようなポインタを再割り当てして、新しいポインタを同じポインタに割り当てないでください。メモリの割り当てが失敗した場合、ヌルポインタが返されるため、以前のデータへの唯一のポインタが失われてしまいます。これはまだ割り当てられています。それはメモリリークです。また、メモリ割り当てが失敗した場合は、割り当てられた領域が元のサイズのままなので、引数リスト内の割り当てを元に戻す必要があります。

    if (i == num_words - 1) 
    { 
        size_t new_size = (num_words * 2); 
        char **new_data = realloc(w, new_size * sizeof(*new_data)); 
        if (new_data == 0) 
         ...handle error; w is still valid, and num_words is still correct too... 
        num_words = new_size; 
        w = new_data; 
    } 
    
関連する問題