1

ここで見つけた関数を使用して、cURLを使用してWebページをメモリに保存しています。

struct WebpageData {
    char *pageData;
    size_t size;
};

size_t storePage(void *input, size_t size, size_t nmemb, void *output) {
    size_t realsize = size * nmemb;

    struct WebpageData *page = (struct WebpageData *)output;

    page->pageData = (char *)realloc(page->pageData, page->size + realsize + 1);
    if(page->pageData) {
        memcpy(&(page->pageData[page->size]), input, realsize);
        page->size += realsize;
        page->pageData[page->size] = 0;
    }

    return realsize;
}

次の行を見つけます。

page->pageData = (char *)realloc(page->pageData, page->size + realsize + 1);

呼び出しごとに数百バイトのメモリリークが発生しています。元のソースから行った唯一の実際の変更は、問題の行を(char *)にキャストすることです。これは、私のコンパイラ(gcc、g ++、特にac / c ++の問題の場合)ですが、gccもキャストされていない状態ではコンパイルされません。ステートメント)が主張しましたが、これがリークの原因であると思います。誰でも解明できますか?

ありがとう

4

3 に答える 3

1

あなたが投稿したコードは(私が知る限り)正しいです。リークしている場合はfree()、ある時点でメモリブロックを忘れているのではないかと思います。 realloc既存のメモリブロックを単純に拡張できない場合は、まったく新しいメモリブロックを作成できます。これは興味深いことです。もちろん、必要以上に大きなブロックを割り当てることもできます。これにより、ファントムリークが発生する可能性があります。

さて、あなたはC ++を使用しているので、私は尋ねなければなりません:なぜあなたは std::vector代わりに使用しないのですか?

struct WebpageData {
    std::vector<char> pageData;
    size_t size;
};

size_t storePage(void *input, size_t size, size_t nmemb, void *output) {
    size_t realsize = size * nmemb;
    WebpageData *page = reinterpret_cast<WebpageData *>(output);

    page->pageData.resize(page->size + realsize + 1);
    memcpy(&(page->pageData[page->size]), input, realsize);
    page->size += realsize;
    page->pageData[page->size] = 0;

    return realsize;
}
于 2010-05-13T05:10:03.933 に答える
0

* nixで開発する場合、一般的に言えば、メモリリークの問題(この場合、メモリが割り当てられている場所はわかっていると思いますが、どこにありますか)について、valgrind( http://valgrind.org/ )を使用してプログラムを実行してみます。解放されていますか?)この場合、絶対に必要で避けられない場合を除いて、c ++プログラムでmalloc、realloc、およびその他の同様のcメモリ管理を使用しないことをお勧めします。c ++メモリ管理ツールを使用するために、これらを回避する必要があります。この場合、メモリが適切に解放されていないと思います。c ++ Vectorsを使用すると、配列のサイズ変更やメモリ割り当てのすべての変更を追跡する必要がなくなるため、ここでの作業がはるかに楽になります。

于 2010-05-13T05:08:24.577 に答える
0

キャストはreallocに何の違いも生じないはずです。メモリリークがありますか?コードはデータを追加しているので、毎回1kBのデータでstorePageを3回要求すると、3kBが保存されます。コードをコピーして貼り付けたときに意図したことですか?そしてもちろん、ブロックが終了したら、どこかでブロックをfree()する必要があります。

他の考え:

  • 再割り当てするメモリは、元々mallocまたはreallocされましたか?

  • データを再割り当てできない場合は、すべてが失われることに注意してください。一時ポインタに再割り当てし、有効な場合にのみpage-> pageDataを上書きすると、これは発生せず、呼び出し元に失敗を報告できます(ただし、実際には発生する可能性はほとんどありませんが、もしそうなら、おそらくはるかに大きな問題が発生するでしょう!)

  • 新しいデータを受信するたびに、ブロックを再割り当てします。必要以上に大きなブロックを割り当て、そこにデータを取得し、すべてのデータを受信した後でのみ正確にフィットするブロックに再割り当てする方がおそらく効率的です。これにより、ブロックを繰り返し再割り当てする必要がなくなります。

于 2010-05-13T05:19:20.260 に答える