0

ハフマンデコーダーを作成しようとしてCで作業しています。このコードは、codearray が初期化されていない場合にのみ機能します。それ以外の場合は、セグメンテーション エラーが発生します。ただし、そのようにすると、valgrind は codearray が初期化されていないと文句を言います。私はdddでそれを経験しましたが、strcpyが呼び出されるとセグメンテーション違反が発生し、その理由がわかりません。

void printtree_inorder(node* n,char* code,char* letarray,char** codearray)
{
    if (n == NULL) {
        return;
    }
    static int counter=0;
    appenddigit(code,'0');
    printtree_inorder(n -> left,code,letarray,codearray);
    remdigit(code);
    if (n->let!='\0') {
       letarray[counter]=n->let;
       strcpy(codearray[counter],code);
       counter++;
    }
    appenddigit(code,'1');
    printtree_inorder(n -> right,code,letarray,codearray);
    remdigit(code);
}

呼び出し関数は次のとおりです。

char code[100]={'\0'};
char** codearray=(char**)malloc(numchars*sizeof(char*));
for (i=0;i<numchars;i++) {
    codearray[i]=(char*)malloc(100*sizeof(char));
}


char* letarray=(char*)malloc((numchars+1)*sizeof(char));
letarray[0]='\0';

printtree_inorder(root,code,letarray,codearray);
4

2 に答える 2

1
for (i=0;i<numchars;i++) {
    codearray[i]=(char*)malloc(100*sizeof(char));
}

これはあなたが話しているコードですか?これは実際には初期化コードではなく、データ コードの余地を作っています。

char** codearray=(char**)malloc(numchars*sizeof(char*));

char * の配列を作成するだけですが、有効なメモリを指していません。したがって、「初期化コード」は、メモリが正しく作成されていることを確認するだけです。

私が本当に怖いのは、カウンター変数が静的であることです。呼び出し

printtree_inorder(root,code,letarray,codearray);
printtree_inorder(root,code,letarray,codearray);

2回目に(外部から)呼び出すと、カウンターが>次にnumcharsになるため、セグメンテーション違反でも終了します。コードを少し書き直して、より安全にしましょう

char* code = (char *)malloc(numchars + 1);
memset(code, 0, numchars + 1);

char* letarray = (char *)malloc(numchars + 1);
memset(letarray, 0, numchars + 1);

char** codearray = (char **)malloc(numchars * sizeof(char *));
memset(codearray, 0, numchars * sizeof(char *));

printtree_inorder(root, code, letarray, codearray, 0);

free(code);
// do not forget the free the other allocations later as well as


void printtree_inorder(node* n,char* code,char* letarray,char** codearray, int counter)
{
    if (n == NULL) {
        return;
    }
    appenddigit(code,'0');
    printtree_inorder(n -> left,code,letarray,codearray, counter);
    remdigit(code);
    if (n->let!='\0') 
    {
       letarray[counter] = n->let;
       codearray[counter] = strdup(code);
       ++counter;
    }
    appenddigit(code,'1');
    printtree_inorder(n -> right,code,letarray,codearray, counter);
    remdigit(code);
}
于 2011-11-26T23:50:53.650 に答える
0

おそらく「初期化された」呼び出しでは、配列が実際にはまったく正しく初期化されていないため、関数がクラッシュします。

「初期化されていない」場合、配列にはおそらく (たまたま) セグメンテーション フォールトにつながらない値が含まれている可能性がありますcodearray

codearray[counter]この関数は、次を指す場所に文字列をコピーしようとします。

strcpy(codearray[counter],code);

関数呼び出しでcodearray[counter]は、配列のみが malloc されたため、これがランダムな値であることを示していますが、要素は特定の値に初期化されていません。strcpy()次に、そのランダムなメモリ アドレスに書き込もうとします。

たとえば、strdup()代わりに を使用して、文字列のコピーにメモリを割り当てる必要がありstrcpy()ます。

于 2011-11-26T23:18:36.557 に答える