0

私がやっていることと正確に一致する質問が見つからないようです。以下は、私の C アプリを問題のある場所まで切り詰めたものです。私はそれが醜いコードであり、いくつかのエラーチェックが欠けていることを知っていますが、この問題を理解するのは私のためだけでした. 現状では、以下のサンプルはすべての「A」を「BCDE」に変換する必要があります。コード内のコメントは、問題を説明しています。(runMe が最初に実行されます)

int runMe2(char *in, char **buffer) {
    long x;
    long b_size = 0; 
    long i_size = 1000;
    long i = 0;
    char t_buffer[1006];

    // Initial malloc small as it will grow
    *buffer = (char *)malloc(2*sizeof(char));
    strcpy(*buffer, "");
    for (x = 0; x < 999; x++)
        t_buffer[x] = 0;
    for (x = 0; x < strlen(in); x++) {
        if (i >= i_size) {
            char *r_buffer;
            b_size = b_size + 1006*sizeof(char);
            i_size = 0;
            // Here is where the problem is.
            // The first time through, i=1000, b_size=1006 and everything is fine
            // The second time throgh, i=1004, b_size=2012 and the heap crashes on the realloc
            r_buffer = (char *)realloc(*buffer, b_size);
            if (r_buffer == NULL)
                exit(0);
            *buffer = r_buffer;
            strcat(*buffer, t_buffer);
            for (x = 0; x < 999; x++)
                t_buffer[x] = 0;
        }
        if (in[x] == 'A') {
            t_buffer[i++] = 'B';
            t_buffer[i++] = 'C';
            t_buffer[i++] = 'D';
            t_buffer[i++] = 'E';
        }
    }
}

int runMe() {
    char *out;
    char in[30000];
    int x = 0;

    // Set up a 29,999 character string
    for (x = 0; x < 30000; x++)
        in[x] = 'A';
    in[29999] = 0;
    // Send it as pointer so we can do other things here
    runMe2(in, &out);
    // Eventually, other things will happen here
    free(out);
}
4

2 に答える 2

3
if (i >= i_size) {
  ...
  i_size = 0;
  ...
}
if (in[x] == 'A') {
  t_buffer[i++] = 'B';
  ...

これは正しくありません。t_bufferifの最後を超えて書くことになりますin元のi_size. iではなく、おそらくそこでリセットするつもりでしi_sizeた。

t_buffer次に、適切に null で終了することが保証されていないときに文字列関数を使用しています。最初の 1000 の値を初期化しますが、ループ内の値を上書きします。and friendsを使用する場合はstrcat、null で終了していることを確認するために、より注意する必要があります。ただしmemcpy、関連する配列の長さがわかっているため、を使用するとコードが単純になります。

for (x = 0; x < strlen(in); x++) {
  ...
  for (x = 0; x < 999; x++)
    ...
    t_buffer[x] = 0;

Uselessで発見されたように、これも正しくありません。そのためには 2 番目の変数を使用するか、より適切に を使用しますmemset

于 2012-10-25T16:46:44.820 に答える
2

楽しみのために、これは機能する別のアルゴリズムであり、あなたのものよりもはるかに単純です。

int runMe2(char *in, char **buffer)
{
    // Count number of A's
    int number_of_As = 0;
    int i, j;
    for (i = 0; 0 != in[i]; i++) {
        if (in[i] == 'A') {
            number_of_As += 1;
        }
    }

    // If number_of_As == 0, you can just do a strdup here and return

    // Because of 1st loop, i == strlen(in), no need to call strlen
    long bytes = (i - number_of_As + (number_of_As * 4) + 1) * sizeof(char);
    // Error check here

    // Only 1 memeory allocation needed
    *buffer = (char *)malloc(bytes);

    // Simple copy loop
    for (i = 0, j = 0; 0 != in[i]; i++) {
            // If it's an A replace
        if (in[i] == 'A') {
            (*buffer)[j++] = 'B';
            (*buffer)[j++] = 'C';
            (*buffer)[j++] = 'D';
            (*buffer)[j++] = 'E';
        }
            // Not an A, just copy
        else {
            (*buffer)[j++] = in[i];
        }
    }
    // Null terminate
    (*buffer)[j] = 0;

    return j;
}
于 2012-10-25T17:33:13.827 に答える