free () в динамической памяти c - PullRequest
2 голосов
/ 23 апреля 2020

Правильно ли я использую free() в приведенном ниже коде? Это утечка памяти? Это проблема использования free() в основной части, а не в функции? Если да, есть метод для освобождения в функции, а не в main?

Этот код копирует массив в другой.

int *copy(const int *arr,int n);

int main(){
    int *p_arr1,*p_arr2;
    int n,i;

    printf("Insert size of array: ");
    scanf("%d",&n);

    p_arr1 = calloc(n,sizeof(int));

    for(i=0;i<n;i++){
        printf("Insert element %d of the array: ",i+1);
        scanf("%d",p_arr1+i);
    }

    p_arr2 = copy(p_arr1,n);

    for(i=0;i<n;i++){
        printf("%d ",*p_arr2);
        p_arr2++;
    }

    free(p_arr1);
    free(p_arr2);

    return 0;
}

int *copy(const int *arr,int n){
    int i;
    int *new;
    new = calloc(n, sizeof(int));
    for(i=0;i<n;i++){
        new[i] += arr[i];
    }

    return new;
}

Ответы [ 2 ]

4 голосов
/ 23 апреля 2020

Пока у вас есть указатель, возвращенный malloc (или в вашем случае calloc), вы можете передавать его в free, когда и где вы хотите, он не обязательно должен быть в той же функции.

Однако после l oop, где вы печатаете содержимое p_arr2, у вас больше нет указателя, возвращаемого calloc внутри функции, потому что вы изменяете указатель в l oop .

Вам необходимо использовать переменную временного указателя для l oop:

int *p_arr2_tmp = p_arr2;
for (size_t i = 0; i < n; ++i)
{
    printf("%d ", *p_arr2_tmp);
    ++p_arr2_tmp;
}

// Now we can free the memory pointed to by the original p_arr2 pointer
free(p_arr2);

Или вместо этого можно использовать простую индексацию массива:

for (size_t i = 0; i < n; ++i)
{
    printf("%d ", p_arr2[i]);
}

// The pointer p_arr2 wasn't modified, so it can be passed to free
free(p_arr2);
3 голосов
/ 23 апреля 2020

В этом l oop

for(i=0;i<n;i++){
    printf("%d ",*p_arr2);
    p_arr2++;
}

значение указателя p_arr2 изменяется, поэтому использование измененного указателя в вызове free приводит к неопределенному поведению.

Вы должны написать

for(i=0;i<n;i++){
    printf("%d ", p_arr2[i] );
}

Также неясно, почему вы используете составной оператор + = в функции вместо оператора =.

new[i] += arr[i];

Функция может быть определена как следующим образом

int * copy( const int *arr, size_t n )
{
    int *new_arr = malloc( n * sizeof( int ) );

    if ( new_arr != NULL ) 
    {
        memcpy( new_arr, arr, n * sizeof( int ) );
    }

    return new_arr;
}

Если вы хотите использовать указатель в l oop, который выводит только что созданный массив, он может выглядеть следующим образом

for ( const int *p = p_arr2; p != p_arr2 + n; ++p )
{
    printf( "%d ",*p );
}
putchar( '\n' );

Если целью является чтобы написать программу, которая использует только указатели и исключает использование оператора индекса и индексов, ваша программа может выглядеть следующим образом

#include <stdio.h>
#include <stdlib.h>

int * copy( const int *arr, size_t n )
{
    int *new_arr = malloc( n * sizeof( int ) );

    if ( new_arr != NULL ) 
    {
        for ( int *p = new_arr; p != new_arr + n; ++p )
        {
            *p = *arr++;
        }
    }

    return new_arr;
}

int main(void) 
{
    size_t n;

    printf( "Insert size of array: " );
    scanf( "%zu", &n );

    int *p_arr1 = calloc( n, sizeof( int ) );

    for ( int *p = p_arr1; p != p_arr1 + n; ++p )
    {
        printf( "Insert element %d of the array: ", ( int )( p - p_arr1 + 1 ) );
        scanf( "%d", p );
    }

    int *p_arr2 = copy( p_arr1, n );

    if ( p_arr2 != NULL )
    {
        for ( const int *p = p_arr2; p != p_arr2 + n; ++p )
        {
            printf( "%d ",*p );
        }

        putchar( '\n' );
    }

    free( p_arr2 );
    free( p_arr1 );

    return 0;
}

Вывод программы может выглядеть как

Insert size of array: 10
Insert element 1 of the array: 0
Insert element 2 of the array: 1
Insert element 3 of the array: 2
Insert element 4 of the array: 3
Insert element 5 of the array: 4
Insert element 6 of the array: 5
Insert element 7 of the array: 6
Insert element 8 of the array: 7
Insert element 9 of the array: 8
Insert element 10 of the array: 9
0 1 2 3 4 5 6 7 8 9 
...