2017-04-23 5 views
-2

文字列を取り込んで特定の文字のインデックスを計算し、そのインデックスに別の構造体ポインタを割り当てるオートコンプリート機能の最初の部分を実装しようとしています。また、可能な補完文を文字列配列に格納します。なんらかの理由で、文字列配列フィールドにアクセスしようとするとプログラムがクラッシュし、その理由がわかりません。これをどうすれば解決できますか?構造体内の配列にアクセスするときにプログラムがクラッシュする

おかげ

struct table { 
    struct table *next[26]; 
    char **complete; 
    int lastIndex; 
    int size; 
}; 

static struct table Base={{NULL},NULL,0,0}; 

void insert(const char *string){ 
    int index=string[0]-'a'; 
    if(Base.next[index]==NULL){ 
     Base.next[index]=(struct table*)malloc(sizeof(struct table)); 
     *Base.next[index]=(struct table){{NULL},NULL,0,0}; 
    } 
    struct table *pointer=Base.next[index]; 
    if(pointer->lastIndex==pointer->size){  //expand complete array 
      pointer->complete[pointer->lastIndex] = strdup(string); //program crashes here 
      pointer->lastIndex=pointer->lastIndex+1;  
    } 
} 
+1

奇妙な動作は、間違ったメモリ操作によって引き起こされる未定義の動作から生じることがよくあります。 **アクセス違反**(セグメント違反)が発生した場合は、[Valgrind](http://valgrind.org)や[AddressSanitizer](https://clang.llvm.org/docs/AddressSanitizer)などのツールを試してみてください.html)を使用して問題の根本を特定します。 「クラッシュ」という言葉を定義することを忘れないでください。 –

+0

'pointer-> complete [pointer-> lastIndex]': 'pointer-> complete'は' NULL'です。逆参照することはできません。 – BLUEPIXY

+0

構造体を割り当てるときは、table.completeを割り当てていません。これは/ someポインタへのポインタであるため、pointer-> complete [n]のように、pointer-> completeは未定義です。 – Mike

答えて

-1

あなたは

const char * string 

はわずかなケースのアルファベットが含まれていることを想定しています。辞書にもアポストロフィーが付きます このケースを追加します。

+0

'static'に間違っています(あなたの答えは' const'を記述しています) –

2

この行のクラッシュ

pointer->complete[pointer->lastIndex] = strdup(string); 

pointer->completeNULLであるためです。つまり、completeのメモリを割り当てるのを忘れてしまいました。

どうすればこの問題を解決できますか?

メモリを割り当てる必要があります。それは、あなたがcharポインタの動的なサイズの配列をしたいようです。だから、reallocを使用して、割り当てられたメモリを拡張して以前の値を保持する必要があります。

のような何か:

char** tmp = realloc(pointer->complete, (pointer->lastIndex + 1) * sizeof(char*)); 
if (tmp == NULL) 
{ 
    // Out of memory 
    exit(1); 
} 
pointer->complete = tmp; 

// Then you can do your normal code 
pointer->complete[pointer->lastIndex] = strdup(string); 

お知らせ:それはreallocあなたが文字列を挿入するたびに使用することは可能だが、それはかなり悪い行うことができます。

新しい文字列ごとにメモリを再割り当てする代わりに、reallocを呼び出すたびにメモリのチャンクを再割り当てする方がよい場合があります。同様:ここ

if (pointer->lastIndex == pointer->size) 
{ 
    // Need more memory 
    // - if it's the first time just start with 10 (or another number) 
    // - else double the size 
    pointer->size = (pointer->size != 0) ? 2 * pointer->size : 10; 
    char** tmp = realloc(pointer->complete, (pointer->size) * sizeof(char*)); 
    if (tmp == NULL) 
    { 
     // Out of memory 
     exit(1); 
    } 
    pointer->complete = tmp; 
} 

私はreallocをやったときに割り当てられたメモリを倍増させることを決めました。代わりにあなたが好きなantのアプローチを使用することができます。倍増の代わりに常に10を追加してください。

ところでlastIndexという名前は、実際にはnextIndexという変数ではありません。

データ構造の最終的な単語

あなたのデータstructur、すなわちstruct tableは私には少し奇妙に思えます。ベースレベルでは、tableのみを使用します。次のレベルでは、tableを使用せず、他の変数のみを使用します。あなたのメモリと動的なメモリ割り当ての一部の両方を救う

struct StringTable { 
    char **complete; 
    int lastIndex; 
    int size; 
}; 

struct table { 
    struct StringTable strings[26]; 
}; 

はあなたのような2つの構造体に構造体を分割すべきであるように私には思えます。

+0

@ SD'Anc - 私の元の答えは愚かなバグでした。今修正されました。 – 4386427

関連する問題