2

動的配列とに問題がありmallocます。私はCにかなり慣れていないので、新人の間違いを許してください(そしてアドバイスしてください)。

問題は、配列(この場合はinput_string)を作成し、それをに渡すことfunc2です。次にfunc2、テストを実行して、input_stringの最初の要素を出力します。

これは、の前の最初の印刷では期待どおりに機能しますmallocが、後はmalloc​​何も印刷されません。printftoステートメントの間にinput_stringに対して何もしないので、これは私には奇妙に思えます。

私はこれらの配列を間違って扱っていると思いますが、よくわかりません。

問題のコードのスニペットは次のとおりです。

更新しました

... // includes not in snippet

/* CONSTANTS */
#define LINE_LEN 80

/* Function declarations */
char* func1(void);
char* func2(int tl, char* input_string);

int main(void) {
    char* input_string;
    int tab_length;
    char* output_string;

    input_string = func1();
    output_string = func2(tl, input_string);

    return 0;
}

char* func1(void) {
    char cur_char;
    char* input_ptr;
    char input_string[LINE_LEN];
    while ((cur_char = getchar()) != '\n' && chars_read < 80) {
        // iterate and create the array here
    }
    input_ptr = &input_string[0]; /* set pointer to address of 0th index */
    return input_ptr;
}

char* func2(int tl, char* input_string) {
    int n = 0, output_idx = 0;
    char* output_ptr;
    printf("\nBefore malloc: %c ", *(input_string));
    output_ptr = malloc(tab_length * chars_read+1);
    if (output_ptr == NULL) {
            printf("Failed to allocate memory for output_ptr.\nExiting");
            exit(1);
    }
    printf("\nAfter malloc: %c ", *(input_string));
    ...
    return output_ptr;
}

追伸:宣言されていない変数は、このコードスニペットの外部で宣言されています。

アップデート

すべての返信とアドバイスをありがとう。大変感謝しております。

4

2 に答える 2

2

func1一時的な文字列へのポインタを返します。あなたはそれを割り当てませんでした。これにより、未定義の動作が発生します。

代わりに、これを行う必要があります。

char* func1(void) {
    char cur_char;
    char* input_ptr = (char*)malloc(LINE_LEN * sizeof(char));
    while ((cur_char = getchar()) != '\n' && chars_read < 80) {
        // iterate and create the array here
    }
    return input_ptr;
}

興味深いことに、あなたはmalloc内部で使用しfunc2ました。

それが終わったらfree、メモリを解放するために呼び出す必要があります。

int main(void) {
    char* input_string;
    int tab_length;
    char* output_string;

    input_string = func1();
    output_string = func2(tl, input_string);

    free(input_string);
    free(output_string);    

    return 0;
}
于 2012-09-14T03:52:51.013 に答える
2

主な問題の1つは、次の場所にあるローカル配列へのポインタを返すことです。

char* func1(void)
{
    char cur_char;
    char* input_ptr;
    char input_string[LINE_LEN];
    while ((cur_char = getchar()) != '\n' && chars_read < 80) {
        // iterate and create the array here
    }
    input_ptr = &input_string[0]; /* set pointer to address of 0th index */
    return input_ptr;
}

input_ptrローカル配列input_string(その0番目の要素)を指すように設定し、そのポインターを返します。関数が戻ると、ポインタは無効になります。スペースは他の目的に再利用されます。

とにかくコンパイラの警告が表示されなかった場合は、さらに多くの警告を設定してコンパイルする必要があります(警告を安全に無視できる理由を理解するのに十分なCがわかるまで、警告を無視しないでください)。私は-Wall -Wextraほとんどいつも、そして-Wall本質的にいつも使っています。


Morpfh指摘しているように、GCC(Mac OS X 10.7.4でテストされた4.7.1)はポインターを返すことについて警告しないので、コンパイラーの支援なしにそれを知っておく必要があります。(returnをreturn input_string;またはreturn &input_string[0];に変更すると、コンパイラーは有用な警告を出します。)

また、コードをコンパイル可能な単位に変換しているときに、EOFを処理せず、結果を;に割り当てていることに気付きgetchar()ました。(この問題の別の議論については、他の多くの質問の中で「EOFチェック」を参照してください)をchar返すので、そうすべきではありません。また、文字列がnullで終了していることを確認する必要があります。また、定数の繰り返しを避ける必要があるため、条件で80を使用するのではなく、LINE_LEN(またはさらに良い方法)を使用してください。また、1つずつバッファオーバーフローが発生しないように注意する必要があります。だから、あなたの私のコンパイル可能なバージョンは:intfgetc()sizeof(input_string)-1func1()

#include <stdio.h>
#include <stdlib.h>
#define LINE_LEN 80
extern char *func1(void);
char *func1(void)
{
    int cur_char;
    char *input_ptr;
    int chars_read = 0;
    char input_string[LINE_LEN+1];

    while ((cur_char = getchar()) != EOF && cur_char != '\n' && chars_read < LINE_LEN)
        input_string[chars_read++] = cur_char;

    input_string[chars_read] = '\0';
    input_ptr = &input_string[0]; /* set pointer to address of 0th index */
    return input_ptr;
}

ローカルポインタを返すため、これはまだ壊れたコードです。

于 2012-09-14T03:54:56.740 に答える