web-dev-qa-db-ja.com

Cでfree()を使用する必要があるのはいつですか?

コードは想定どおりに機能しますが、malloc()によって割り当てられたメモリを解放することはありません。

できる限りどこでもメモリを解放しようとしましたが、どこで行ってもプログラムが壊れてしまいます。具体的には、「ダブルフリーまたは破損エラー」が発生します。これは、free()malloc()が実際に何をするかについての質問です。無料に関するすべての問題は主にあります:

int main(int argc,  char *argv[]){
if(argc!=2){
    exit(1);
}

printf("CSA WC version 1.0\n\n");

int length = strlen(argv[argc-1]);
char file_to_open[length];
strcpy(file_to_open, argv[argc-1]);

//printf("filename:%s\n",file_to_open);

//create counters for output
int count_number_of_lines = 0;
int count_number_of_words = 0;
int count_number_of_characters = 0;

//create int size of default array size
int current_array_size = pre_read(file_to_open);
//printf("number of lines: %i\n",current_array_size);

//create string array of default size
char *strings_array[current_array_size];

//create a pointer to catch incoming strings
char *incoming_string=NULL;

int done=0;
while(done==0){
    incoming_string=get_line_from_file(file_to_open, count_number_of_lines);
    if(incoming_string!=NULL){
        incoming_string=csestrcpy2(incoming_string);
        //printf("incoming line: %s\n",incoming_string);
        strings_array[count_number_of_lines]=(char*)malloc(strlen(incoming_string+1));
        strings_array[count_number_of_lines]=csestrcpy2(incoming_string);
        //printf("added to array:%s\n",strings_array[count_number_of_lines]);
        count_number_of_lines++;
        count_number_of_characters=(count_number_of_characters+(strlen(incoming_string)-1));
    }
    else{
        done=1;
    }

}
//all data is stored in a properly sized array


//count all words in array
int count=0;
int Word_count=0;
char *readline;

while(count<current_array_size){
    readline = csestrcpy2(strings_array[count]);
    printf("line being checked: %s", readline);

    int i=0;
    int j=1;

    while( j< strlen(readline)+1 ){
        if(strcmp(readline,"\n")!=0){
            if( (readline[i] == ' ') && (readline[j] != ' ') ){
                Word_count++;
            }
            if( (readline[i] != ' ') && (readline[j] == '\n') ){
                Word_count++;
            }
        }
        i++;
        j++;
    }
    count++;
}
printf("current Word count: %i", Word_count);
return 0;
}



char* csestrcpy2(char* src){

int i = 0;
char *dest;
char t;
dest = (char*) malloc(MAX_LINE);

while( src[i] != '\0'){

    dest[i] = src[i];
    i++;

}

dest[i] = '\0';
//printf("length:%i\n",i);
free(dest);

return dest;
}
8

一般に、動的に予約されているメモリを解放するだけで済みます。つまり、次のようなステートメントがある場合です。

_int *my_int_pointer;
my_int_pointer = malloc(sizeof(int));
_

mallocによって割り当てられた(予約された)メモリを解放する必要があるよりも。プログラムの最後にfreeを使用して解放するよりも、どこで解放するかわからない場合。

_free(my_int_pointer);
_

あなたのファイルでは、あなたが読んだファイルに(while(done==0)ループで)新しい行があるときはいつでもメモリが割り当てられているように見えます。したがって、このループのifの後に毎回、変数によって使用されていたメモリを解放する必要があります。

さらに、readline変数に割り当てられたメモリを解放する必要があります。しかし、前に指摘されたように、そこでメモリリークが発生する可能性があります。

お役に立てれば。

編集:わかりました-私はすでにcsestrcpy関数について疑問に思っていました。この関数を見てみましょう:

_char* csestrcpy2(char* src){
    int i = 0;
    char *dest;
    char t;
    dest = (char*) malloc(MAX_LINE); /*<<- This allocates memory that has to be freed*/
    while( src[i] != '\0'){
        dest[i] = src[i];
        i++;
    }
    dest[i] = '\0';
    //printf("length:%i\n",i);
    free(dest);                  /* This frees the memory, but you return a pointer */
    return dest;                 /* to this memory. this is invalid.                */
}
_

ただし、解放できるのは、その関数のsrcポインターです。ただし、基になるメモリが解放された後は、ポインタは情報を保持できません。これは、メモリ内で書き込みや読み取りを行わない場所を指しているだけです。

さらに、関数は「\ 0」がない限り、文字列をコピーします。ターミネータがない場合はどうなりますか?この関数は、あるべきではないメモリアドレスからコピーし続けます!

その関数は使用しないでください;)

14
Florian

free()の呼び出しが成功するたびに、malloc()の呼び出しが必要です。

それはそうではありません必然的にコードに同じ数のmalloc()free()の呼び出しが必要であることを意味します。これは、プログラムの実行時に実行されるすべてのmalloc()呼び出しについて、free()を呼び出し、malloc()から取得したポインター値を渡す必要があることを意味します。 malloc()はメモリを割り当てます。 free()は、割り当てられたメモリが終了したことをシステムに通知します。

(プログラムの終了時にfree()ing割り当てられていないメモリはオペレーティングシステムによって再利用されるため、ほぼ確実に回避できますが、スタイルとグッドプラクティスの問題として、malloc()sとfree() s。)

calloc()realloc()の呼び出しを無視しています。

6
Keith Thompson

動的メモリ割り当て(malloc)は、要求されたサイズのメモリブロックを割り当て、このブロックの先頭へのポインタを返します。このブロックをメモリから取得したため、タスクの完了後にこれをメモリに戻すことをお勧めします。

今あなたの質問の答えとして、あなたは常に安全な側にいるためにあなたは戻る前に無料の関数を呼び出すことができます。

main{
    int *i;
    ..
    ..
    i=(int *)malloc(sizeof(int));
    ...//so something with i
    ..
    free(i);
    return 0;
}
3
Dayal rai

原則として、すべてのmallocには対応するfreeが必要です。ただし、何かを2回freeすることはできません(これまでに気付いたように)。コードにfreeの呼び出しがないため、問題がどこにあるかを特定することはできませんが、mallocメモリをreadlineに割り当てていることにすぐに気付きました。 var] _はループ内にありますが、ループの最後でfreereadlineを呼び出さないため、そこでメモリリークが発生しています。

0
Ed S.

mallocfreeを「開始」と「終了」と考えてください。 mallocに電話するときはいつでも、必要なことを実行し、完了したら、常にfreeに電話してください。必ず一度だけ解放してください。double-freeは実行時エラーです。

mallocによって返される値を何らかの理由で失った場合(はい、これがコードで起こっていることです)、メモリリークが発生します(そして、地獄の門が開かれます、ヤダヤダ)。

繰り返しますが、mallocが返すものはすべて解放します(nullを除く)。

0
Chris Eberle
        i++;
        j++;
        /// free here
        free(readline);
    }
    count++;

}
printf("current Word count: %i", Word_count);

//free here as well
for(int k = 0; k < count_number_of_lines; k++)
{
    free(strings_array[count_number_of_lines]);
}

return 0;
}

これはうまくいくはずです。

一般に、calloc/malloc/reallocを使用して動的に割り当てられたメモリは、ポインタがスコープ外になる前にfree()を使用して解放する必要があります。

'new'を使用してメモリを割り当てる場合は、 'delete'を使用してメモリを解放する必要があります。

0
Jan S

この行:

_strings_array[count_number_of_lines]=(char*)malloc(strlen(incoming_string+1));
_

はその隣の行によって上書きされているため、削除できます。

また、mallocによって作成されたメモリを解放するには、最後のループの_count++_の後にfree(readline)を追加する必要があります。

0
alf