2

Cでstr_replace関数を構築しようとしています(Cを学ぶため)。少し簡単にするために、2 つのヘルパー関数を作成することにしました。そのうちの 1 つは次のプロトタイプを持ちます。

char * str_shift_right(const char * string, char fill, int32_t n);

文字列を取り、指定された文字列filln番目の位置に文字を追加します。完全なコードは次のとおりです。

// replace the nth char with 'fill' in 'string', 0-indexed
char * str_shift_right(const char * string, char fill, int32_t n) {
    // +1 the null byte, +1 for the new char
    int32_t new_size = (int32_t) strlen(string) + 2;
    char * new_string = NULL;
    new_string = calloc(new_size, sizeof(char));

    new_string[new_size - 1] = '\0';
    int32_t i = 0;
    while (i < strlen(string) + 1) {
        // insert replacement char if on the right position
        if (i == n) {
            new_string[i] = fill;

        // if the replacement has been done, shift remaining chars to the right
        } else if (i > n) {
            new_string[i] = string[i - 1];

        // this is the begining of the new string, same as the old one
        } else {
            new_string[i] = string[i];
        }

        i++;
    }

    return new_string;
}

この関数がメモリをリークしていないことを確認したかったので、次のコードを実行してみました。

int main(int argc, const char * argv[])
{    
    do {
        char * new_str = str_shift_right("Hello world !", 'x', 4);
        printf("%s", new_str);
        free(new_str);
    } while (1);

    return 0;
}

ただし、アクティビティ モニター (Windows のプロセス マネージャーのような Mac OSX アプリケーション) でメモリ使用量を監視すると、RAM がかなり速く消費され、プログラムが停止すると使用できなくなるようです。実行中。

それはメモリリークとは何ですか?もしそうなら、私は何を間違えましたか?free(new_str)呼び出しはメモリを解放するはずではありませんか?

ご協力いただきありがとうございます。

編集 1 : PaulR によって発見された 1 つのエラーによって修正されました。問題は残ります。

4

4 に答える 4

6

RAM がすぐに使い果たされ、プログラムの実行が停止すると RAM が使用できなくなるようです。

どのRAM使用量を見ていますか? システム内の RAM の合計使用量は?

もしそうなら、あなたが見ているのはおそらくあなたの端末が使用しているメモリです.プログラムが出力するすべての文字は端末によってRAMに保存されます. もう一度試してください。ただし、今回は出力がターミナルに表示されないようにします。

./program > /dev/null

原則として、リークしているメモリの量に関係なく、プログラムが終了すると常に自動的に解放されます。そして、私はあなたのプログラムにリークを見つけることができません.

于 2013-05-27T16:48:56.183 に答える
2

更新:どのように測定していますか? これは UNIX では不可能です。「[メモリ] は、プログラムの実行が停止したときに使用できなくなります」。多分あなたは間違った番号を見ているだけですか?!?

どこに記憶があるべきかわかりません。などのツールを使用してみてくださいvalgrind

前述の無効な書き込みについては、何度も議論されてきました。これでメモリ管理情報を破壊しているのかもしれません。C ライブラリが、割り当てられたメモリ フラグメントを追跡するために、割り当てられた各メモリ チャンクの直前および/または直後にバイトを使用するのを見てきました。したがって、この方法でサイズをゼロにし、この方法でメモリ管理を無効にしている可能性があります。本当に、と同様のツールを使用してください。valgrind

ただし、コードを単純化したい場合もあります。

  1. とにかく完全に上書きしようとしているメモリをゼロにする必要はありません。
  2. 位置が既にわかっている場合は、ループを使用する必要はありません。
  3. 末尾をコピーすることもできます\0
  4. 実際にはunsignedを使用します。が負の場合、上記のコードは警告しません。それと負であってはなりません。size_tfillsize_t

したがって、これで十分なはずです(私はこれをコンパイルテストしませんでした-あなたがしたいかもしれません):

char* str_shift_right(const char* string, char fill, size_t n) {
  size_t len = strlen(string);
  char* new_string = malloc(len + 2, sizeof(char));
  memcpy(new_string, string, n);
  new_string[n] = fill;
  memcpy(new_string + n + 1, string + n, len - n + 1);
  return new_string;
}

最後memcpy\0ここに末尾をコピーします。全体として、C コンパイラはこのコードをより適切に最適化する可能性があり、memcpy通常は非常に適切に処理されます。さらに、実際にははるかに読みやすくなっています。

于 2013-05-27T16:48:49.493 に答える
0

言及されていますが、プログラムにメモリリークがあると思われる場合は、システムモニターを監視するだけで結論を出すのではなく、代わりにvalgrindを使用することを強調する価値があると思います。

ここからダウンロードしてください:

http://valgrind.org/downloads/current.html

于 2013-05-27T16:59:53.803 に答える