Jak zwolnić całą tablicę, której elementy zostały indywidualnie przydzielone w pamięci przez wywołania malloc / calloc [duplicate]

Aug 16 2020

Z tego, co wiem, malloc i calloc są po prostu księgowymi interfejsami API w pamięci podstawowej. Mając to na uwadze, zastanawiam się, czy wywołanie free () zwolni całą tablicę, której poszczególnym elementom przydzielono pamięć poprzez niezależne wywołania malloc (lub calloc).

Dokładnie mam następujący kod:

int *num,* num_start;

num_start=num;

for(i=0;i<N;i++)
{
    num = (int *)calloc(0, sizeof(int));
    num++;
}

free(num_start);

Czy free(num_start)niezależnie zwolni całą tablicę N elementów całkowitych, do których przydzielono dynamicznie miejsce?

Odpowiedzi

1 P__JsupportswomeninPoland Aug 16 2020 at 10:09

Wysłany przez Ciebie „kod” nie ma żadnego sensu i jest błędny.

int *num, num_start;
num_start=num;

num_start to liczba całkowita, a nie wskaźnik.

for(i=0;i<N;i++)
{
    num = (int *)calloc(0, sizeof(int));
    num++;
}

szczerze mówiąc nie rozumiem, co ten kod ma robić, ale na pewno jest źle

jeśli chcesz przydzielić pamięć dla Nliczb całkowitych

int *num = calloc(N, sizeof(*num));

a do uwolnienia potrzebujesz tylko

free(num);

Lub jeśli chcesz przydzielić wskaźnik do przechowywania N wskaźników do N liczb całkowitych

int **allocate(size_t N)
{
    int **num = malloc(N * sizeof(*num));
    for(size_t i=0; i<N; i++)
    {
        num[i] = calloc(N, sizeof(**num));
    }
    return num;
}

void arrayfree(int **num, size_t size)
{
    for(size_t i = 0; i < size; i++)
    {
        free(num[i]);
    }
    free(num);
}

Kiedy przydzielasz pamięć, musisz sprawdzić, czy operacja się powiodła. Te sprawdzenia nie są uwzględnione w przykładzie, aby kod był łatwiejszy do odczytania.

tadman Aug 16 2020 at 09:55

Funkcje calloc()i malloc()zwracają wskaźnik do alokacji, która podwaja się jako uchwyt zwalniający tę pamięć. Chociaż możesz tworzyć kopie tego wskaźnika i manipulować nimi według własnego uznania, dzwoniąc do free()ciebie, musisz podać oryginalną wartość .

To znaczy, że to działa:

// Original allocation
int* x = calloc(42, sizeof(int));

// Making a new (independent) copy of the pointer to a new pointer
int* p = x;

// Arbitrary pointer manipulation and mangling
x++;

// Freeing with the copied value
free(p);

Możesz też zaznać nieco przygód, o ile wrócisz do pierwotnego celu:

int* x = calloc(42, sizeof(int));

x += 40;
x -= 30;
x += 10;
x -= 13;
x -= 7;

free(x);

Gdzie tutaj xwrócił do swojej pierwotnej wartości po krótkiej podróży. Ogólnie rzecz biorąc, lepiej jest zachować oryginalny wskaźnik niż później go rekonstruować. Rób kopie, jeśli zamierzasz nimi manipulować.