6

私はCに非常に慣れていないので、次のコードの何が問題になっているのか理解できないようです。

int main() {
    char filen[] = "file.txt";
    FILE *file = fopen ( filen, "r" );
    if ( file != NULL )
    {
        char line [ 128 ];
        while ( fgets ( line, sizeof line, file ) != NULL ) /* read a line */
        {
            int i;
            char *result;
            for(i=0; i< NUM;i++)
            {
                char *rep;
                rep = (char *) malloc (sizeof(mychars[i][0]));
                strcpy(rep, mychars[i][0]);
                char *with;
                with = (char *) malloc (sizeof(mychars[i][1]));
                strcpy(with, cgichars[i][1]);
                result = (char *) malloc (sizeof(char) * 128);
                result = str_replace(line, rep, with);
            }


            fputs(result, stdout);
        }
    }
    fclose ( file );


    return 0;
}

Valgrindは私にこのエラーを与えています:

==4266== Invalid read of size 1
==4266==    at 0x4C286D2: __GI_strlen (mc_replace_strmem.c:284)
==4266==    by 0x5118A8D: fputs (iofputs.c:37)
==4266==    by 0x400A0F: main (repl.c:35)
==4266==  Address 0x0 is not stack'd, malloc'd or (recently) free'd

repl.cは、このコードの終わりに向かってfputsで始まる行に対応します。

また、mycharsは次のような2次元配列です。

char *mychars[NUM][2] = {
  "a", "97",
  "b", "98",
  ....

誰かがこれを修正する方法を教えてもらえますか?また、現在のコード(特にmallocを使用)をどのように改善する必要があるかについてのアドバイスをいただければ幸いです。

編集: str_replaceのコード

char *str_replace(char *str, char *orig, char *rep) {
  char buffer[4096];
  char *p;

  if(!(p = strstr(str, orig)))
    return NULL;

  strncpy(buffer, str, p-str);
  buffer[p-str] = '\0';
  sprintf(buffer+(p-str), "%s%s", rep, p+strlen(orig));

  return buffer;

}

str_replace、およびmainの2つの新しいコードを編集します。

テストの目的で、str_replaceメソッドを次のメソッドに置き換えました。

Cの文字列を置き換える機能は何ですか?

そして私のメインは少し変更されています:

int main() {
    static const char filen[] = "file.txt";
    FILE *file = fopen ( filen, "r" );
    if ( file != NULL )
    {
        char line [ 128 ];
        while ( fgets ( line, sizeof line, file ) != NULL ) /* read a line */
        {
            int i;
            char *result;
            for(i=0; i< NUM;i++)
            {
                char *rep;
                rep = (char *) malloc (sizeof(mychars[i][0]));
                strcpy(rep, mychars[i][0]);
                char *with;
                with = (char *) malloc (sizeof(mychars[i][1]));
                strcpy(with, mychars[i][1]);
                result = str_replace(line, rep, with);
            }


            fputs(result, stdout);
        }
    }
    fclose ( file );


    return 0;
}

しかし、私はまだ得ています

==6730== Invalid read of size 1
==6730==    at 0x4C286D2: __GI_strlen (mc_replace_strmem.c:284)
==6730==    by 0x5118A8D: fputs (iofputs.c:37)
==6730==    by 0x400995: main (repl.c:29)
==6730==  Address 0x0 is not stack'd, malloc'd or (recently) free'd

おそらく、これの最も苛立たしい部分は、これらの無効な読み取りエラーが何であるかを知らないことです。

編集3for ループの中央にあるコードを次のように更新しました。

        int i;
        char* result;
        result = &line[0];
        for(i=0; i< NUM_CGICHARS;i++)
        {
            char *rep;
            rep = (char *) malloc (sizeof(char));
            strcpy(rep, cgichars[i][1]);
            char *with;
            with = (char *) malloc (sizeof(char)*3);
            strcpy(with, cgichars[i][0]);
            result = str_replace(result, rep, with);
            fputs(result, stdout);
            free(rep);
            free(with);
        }

そして今、私は出力を得始めています!ただし、たった2回の反復の後、セグメンテーション違反が発生し、valgrindによって次のような問題が発生します。

==9130== Invalid read of size 1
==9130==    at 0x4C286D2: __GI_strlen (mc_replace_strmem.c:284)
==9130==    by 0x5118A8D: fputs (iofputs.c:37)
==9130==    by 0x4009DF: main (teststep1.c:27)
==9130==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
4

3 に答える 3

7

この2行で

            result = (char *) malloc (sizeof(char) * 128);
            result = str_replace(line, rep, with);

最初にそのためのスペースを割り当てresult、その後すぐに の戻り値で上書きして解放しますstr_replace。その関数はおそらく を返す0ので、fputs失敗します。

ところで、 return の をキャストしないでくださいmalloc。C ではこれは不要であり、プロトタイプを含めるのを忘れたという事実を隠す可能性があります。

編集:あなたのstr_replace関数は、メモリ処理において完全に間違っています。ポインターをローカル変数に返さないでください。関数を終了した後は、スペースは無効になります。

于 2012-04-12T21:27:20.700 に答える
0

NUMが 0 の場合、result初期化されておらず0、偶然である可能性があります。

への呼び出しの結果をチェックしていないため、失敗はポインターmalloc()に書き込もうとしている可能性があります。NULL

どこでmychars宣言されていますか?

于 2012-04-12T21:24:17.183 に答える