2016-03-30 13 views
0

何度も変更したこのコードに問題があります(ただし、エラーは常に表示されます)。 "filter"の最後のインデックスを解放する際にエラーが発生したようです。strange free()無効なポインタC

ここで
char** read_and_filter(int fd) { 
    char buf[MAXLENGTH]; 
    char **bufs=NULL; 
    char ch; 
    int j = 0, len = 0, t = 0; 
    while (!t && read(fd,&ch,1) == 1) { 
    switch (ch) { 
    case '\n': 
     t = 1; 
    case ' ': 
     bufs = realloc(bufs, (j+1)*sizeof(char*)); 
     bufs[j++] = strndup(buf,len); 
     memset(buf,0,len); 
     len = 0; 
     break; 
    default: 
     buf[len++] = ch; 
    } 
    } 
    bufs[j] = 0; 
    return bufs; 
} 

int main(int argc, char **argv) { 
    char **filter; 
    int i,fd = open("input.txt",O_RDONLY); 
    filter = read_and_filter(fd); 
    for(i = 0; filter[i]; i++) { 
    printf("%s\n",filter[i]); 
    free(filter[i]); 
    } 
    return 0; 
} 

が出力されます:

0x1521030 
HOME 
0x1521050 
2 
0x1521070 
A 
0x1521010 
8 
0x15210c0 
D 
*** Error in `./test': free(): invalid pointer: 0x00000000015210c0 *** 

私もvalgrindのとそれをデバッグしようとした(?それは文字の合計が8である、奇妙なノーながらアロケータは9バイトを解放しようとすることを私に言います) gdbしかし何も働かなかった。 INPUT.TXTの 最初の行は "HOME 2 A 8 Dの\ n" は

+0

文書化されていない変数名は子猫を泣かせます。 'j'? 't'?コードを読む時間を取っているときにそれらを理解するのは簡単ですが、合理的な命名で簡単にすることができます。たとえあなたが自分で簡単に気にしなくても、他の人に報酬なしであなたの問題を助けようとしているときは、仕事をできるだけ簡単にするために他人に借りなければなりません。それを超えて、あなたの出力はあなたが提供したプログラムと一致していないようです。表示されているコードが印刷しない各文字列の前にポインタ値が表示されます。 – mah

+0

これらのステートメントは、 'buf [len ++] = ch;'を解放する際に問題を生じました。ポインタが指しているものに変更するとき。 – ameyCU

+2

@ameyCUうーん、いいえ、どんな形でもポインタを変更しません。 –

答えて

7

これらの線が

bufs = realloc(bufs, (j+1)*sizeof(char*)); 
bufs[j++] = strndup(buf,len); 

あなたは1つのポインタ(jは0であった)のためのメモリを得て実行される最初の時間です。これは終値NULLあなたは、このように未定義の動作を持っているので、あなたが割り当てられたメモリを超えて書いている

bufs[j] = 0; 

と関数の最後に書くためにスペースを残しません。同様に、バッファ長を拡張するたびに

+0

私はBUFS [J] = 0を取る場合:0x1a14030 HOME 0x1a14050 0x1a14070 あなたがやるよりも、もう一つの要素を割り当てる必要があります 0x1a14010 0x1a140c0 D 0x21でセグメンテーションフォールト – JoAccount

+0

。 'realloc(bufs、(j + 2)* sizeof(char *))' –

+0

ループの要素を解放した後に 'free(filter) 'する必要があります。 –

6

bufs[j] = 0;の末尾にread_and_filterが割り当てられていないメモリに書き込みます。その余分な0のためrealloc - bufsのためにあなたは決して決してありません。

0

メモリリークの2つの場所から発生している - のstrdupとのrealloc

一つの答えは、mallocを使用して、主にバッファ用のメモリの初期割り振りを行い、その後、機能に割り当てられたメモリへのポインタを渡すことです。この関数はバッファを再割り当てし、そのバッファにデータをコピーすることができます。

関数から復帰したとき、mainは有効なポインタを持つバッファから直接データにアクセスし、終了する前にそのメモリを解放することができます。

valgrindによると、次のようにメモリが失われることはありません。

void read_and_filter(int fd, char **bufs) { 
    char buf[100]; 
    char ch; 
    int j = 0, len = 0, t = 0; 
    while (!t && read(fd,&ch,1) == 1) { 
    switch (ch) { 
    case '\n': 
     t = 1; 
    case ' ': 
     *bufs = realloc(*bufs, (j + 2)*sizeof(char*)); 
     strncpy(bufs[j++], buf, len); 
     memset(buf,0,len); 
     len = 0; 
     break; 
    default: 
     buf[len++] = ch; 
    } 
    } 
    bufs[j] = 0; 
    return; 
} 

int main(int argc, char **argv) { 
    char *bptr = malloc(1); 
    int fd = open("input.txt", O_RDONLY); 

    read_and_filter(fd, &bptr); 

    printf("%s\n", bptr); 
    free(bptr); 
    return 0; 

は、しかし、私は、これは完全にOPの意図した機能を複製することを確認することはできませんが、全体的なアプローチは、メモリの問題に対処ありません。

関連する問題