0

私の教授はrealloc()、この特定の例でうまくいかない理由を見つけるための「課題」を与えました。このサイトを検索してみましたが、割り当てられたメモリ ブロックのサイズを決定する実際の方法がないため、再割り当てが必要なメモリ ブロックの新しいサイズがわからないmalloc()ため、機能しないと思います。realloc()

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
int main ()
{
    MEMORYSTATUS memInfo;
    memInfo.dwLength = sizeof(MEMORYSTATUS);
    GlobalMemoryStatus(&memInfo);
    double slobodno = memInfo.dwAvailVirtual/1024./1024.;

    printf("%g MB\n",slobodno);
    int br=0,i,j;

    char **imena,*ime,*temp,*bbb=NULL;
    imena=(char**) malloc(sizeof(char*)*(br+1));
    while(1)
    {
        printf("Unesite ime: ");
        ime=(char*) malloc(sizeof(char)*4000000);
        gets(ime);
        printf("%u\n", strlen(ime));
        ime=(char*) realloc(ime,strlen(ime)+1);

        GlobalMemoryStatus(&memInfo);
        slobodno = memInfo.dwAvailVirtual/1024./1024.;
        printf("%g MB\n",slobodno);

        if (strcmp(ime,".")==0)
           {free(ime);free(imena[br]);break;}
        imena[br++]=ime;
        imena=(char**) realloc(imena,sizeof(char*)*(br+1));
    }

    for (i=0;i<br-1;i++)
        for (j=i+1;j<br;j++)
            if (strcmp(imena[i],imena[j])>0)
            {
                temp=imena[i];
                imena[i]=imena[j];
                imena[j]=temp;
            }


    //ovde ide sortiranje
    for (i=0;i<br;i++)
        printf("%s\n",imena[i]);

    for(i=0;i<br;i++)
       free(imena[i]);

    free(imena);

    return 0;
}

注: 教授は、使用可能なメモリを出力するための行を追加したので、それがrealloc()機能しないことがわかります。入力するすべての新しい文字列はsizeof(char)+4000000バイトを占有するだけで、再割り当てすることはできません。私はその理由を見つけようとしています。前もって感謝します

4

4 に答える 4

3

Windows のページ サイズに関係があるような気がします。たとえば、4000000 を 400000 に変更すると、メモリを再利用できることがわかります。

4000000 を割り当てると、Windows は「巨大な」ページ サイズ (4MB) を使用するようになり、(私にはわからない) なんらかの理由で、realloc が期待どおりに機能しないと思います (つまり、未使用のメモリを他のユーザーが使用できるようにします)。配分)。

これは、Realloc() が Windows でメモリを正しく解放しないに関連しているようですが、これは VirutalAlloc に言及していますが、realloc が機能しない正確な理由を明確にするかどうかはわかりません。

于 2012-11-07T20:33:01.853 に答える
0

MSDNから:

引数は、メモリブロックのmemblock先頭を指します。の場合、memblockと同じように動作しNULL、新しいバイトブロックを割り当てます。reallocmallocsize

したがって、その行は毎回新しいメモリになりますime=(char*) realloc(NULL,sizeof(char)*4000000);malloc

于 2012-11-07T20:21:32.360 に答える
0

問題は、reallocが元のブロックのサイズを認識していないということではありません。その情報はプログラマーには利用できませんが、reallocで利用できる必要があります(ブロックがmallocまたはcallocで割り当てられている場合でも)。

この線

ime=(char*) realloc(ime,strlen(ime)+1);

以前に割り当てられたブロックをコンテンツに正確に合わせるために縮小しているように見えますが、実際にメモリのブロックを縮小し、残りを新しい割り当てに再び使用できるようにする必要はありません。

編集

私が今考えたもう1つのこと:reallocによる縮小は問題なく機能するかもしれませんが、ライブラリが次の割り当てのためにメモリを保持しているため、メモリはランタイムライブラリによってOSに返されません。唯一、次の割り当ては、reallocで解放されたメモリに収まらないほど大きなブロックに対するものです。

于 2012-11-07T20:22:39.333 に答える
0

reallocメモリを解放しません。reallocこれらの関数はメモリの大きなブロック (「ヒープ」と呼ばれます) で動作し、 / malloc/を呼び出すとチャンクを分割しますcalloc。現時点でヒープ内にあるよりも多くのメモリが必要な場合は、オペレーティング システムに追加のメモリを要求することによってヒープが拡張されます。

メモリ ブロックを小さくするために呼び出すreallocと、必要のないメモリが*alloc別の要求で再度配布できるようになるだけです。ヒープを縮小してメモリをオペレーティング システムに戻すこともありませreallocん。free(これが必要な場合は、Windows などのオペレーティング システムのネイティブ メモリ割り当て手順を呼び出す必要がありVirtualAllocます。)

于 2012-11-07T20:37:39.267 に答える