-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;
}
4

2 に答える 2

1

最初の割り当てコードは次のとおりです。

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

これらはどちらも 10 バイトのメモリを割り当てます。あなたの2番目のものは読むべきです:

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

また:

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

これらはどちらも、10 個のポインターに十分なメモリを割り当てます (元のコードの 8 倍のメモリになる可能性があります)。2 つ目は間違いなく優れたスタイルです。最初は間違いなく古典的なスタイルです。C では、キャストオンmalloc()は必要ありません。C++ ではそうです。

これがすべての問題ではないかもしれません。それはほぼ確実に寄与因子です。

また、メモリ割り当てをチェックしていません。それはお勧めできません。常にチェックする必要があります。


このコード:

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

2つのアカウントで火遊びをしています(さらに、以前に診断された問題の繰り返し):

  1. 引数リスト内での代入は...一般的には良い考えではないと考えられています。私はその場でコードを書くことはせず、レビューを求められたコードを送り返しました。技術的に間違っているわけではありません。それが動作します。しかし、その後に続く保守プログラマーの生活が楽になるわけではありません。

  2. などのポインターを再w割り当てして、新しいスペースを同じポインターに割り当てないでください。メモリの割り当てに失敗すると、null ポインターが返されるため、まだ割り当てられている前のデータへの唯一のポインターが失われます。それはメモリリークです。また、メモリの割り当てに失敗した場合は、割り当てられたスペースがまだ元のサイズであるため、引数リスト内の割り当てを元に戻す必要があります。私はあなたが使用する方が良いと思います:

    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;
    }
    
于 2012-04-06T03:06:09.267 に答える
0

変数は配列num_wordsの現在の最大サイズを保持しますがw、それは配列内の実際の単語数と同じではありません。

配列をループwすると、あまりにも多くのアイテムをループしています - 一部の要素にはw有効な文字列が含まれていません - それらを印刷しようとすると、セグメンテーション違反が発生します。

于 2012-04-06T03:05:57.483 に答える