как работает free ()? - PullRequest
       1

как работает free ()?

1 голос
/ 10 августа 2011
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main ()
{
    int * ptr;
    printf("before malloc pointer is :%p \n",ptr);
    printf("before malloc valu is :%d \n",*ptr);
    ptr = malloc(sizeof(int));
    printf("after malloc pointer is %p \n",ptr);
    printf("after malloc valu is :%d \n",*ptr);
    int jig=32;
    *ptr = jig;
    printf("after assignment valu is : %d\n",*ptr);
    free(ptr);
    printf("after free %p \n",ptr); // after free pointer holds sane address then 
    printf("after fee is %d\n",*ptr); // why it coudnt print that???
    return 0;
}

вывод:

 before malloc pointer is :0x6edff4 
 before malloc valu is :7265660 
 after malloc pointer is 0x9a52008 
 after malloc valu is :0 
 after assignment valu is : 32
 after free 0x9a52008 
 after fee is 0

после того, как указатель free still хранит адрес этой памяти, почему мы не можем напечатать значение этой памяти ???

что делает free () ??

делает все памяти как 0 .. ??

Ответы [ 4 ]

4 голосов
/ 10 августа 2011

после того, как указатель свободной памяти хранит адрес этой памяти, почему мы не можем напечатать значение этой памяти ???1002*

Поскольку память больше не принадлежит вам.Вы free сделаете это, что означает, что ОС разрешено использовать ее повторно, как она считает нужным, там, где ей нужно выделить больше памяти.Вы больше не являетесь его владельцем, поэтому у вас больше нет бизнеса, который рассматривает значение данных, хранящихся в этой памяти.

Обратите также внимание на то, что:

int *ptr;
...
printf("Before malloc valu is :%d\n", *ptr);

в равной степени недопустимо.ptr содержит значение мусора и может указывать куда угодно.Разыменование не гарантирует, что это будет область памяти, к которой вы можете получить доступ.

В обоих этих случаях используется неопределенное поведение , что означает, что стандарт говорит: «НЕ ДЕЛАЙ ЭТОГО», и есливы игнорируете стандарт, ваш код будет ужасно ломаться всякий раз, когда ваш начальник смотрит.

что делает free () do .?

делает все память просто равной 0 ..??

Нет, не обязательно.ОС часто обнуляет неиспользуемую память в фоновом режиме, чтобы звонить на calloc быстрее, но free только сообщает операционной системе: «Я закончил с этой памятью, делай с ней все, что тебе нужно».Операционная система обычно обновляет некоторые служебные данные, чтобы указать, что блок памяти больше не принадлежит процессу, так что более поздний вызов malloc может использовать его, если это необходимо.

3 голосов
/ 10 августа 2011

Интересная вещь о malloc() и free() заключается в том, что они на самом деле не меняют память, которую они вам дают, они просто меняют то, как это "мыслит".

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

Когда вы закончите с этим, вы free() это - но это все еще там. Это все та же память [1], просто она больше не считается "твоей". Так что кто-то другой может использовать его.

[1] Я предположил, что с виртуальной адресацией это не всегда может быть правдой. Но обычно это так.

3 голосов
/ 10 августа 2011

free возвращает память в систему. Это партнерская операция до malloc. Все блоки памяти, которые вы выделяете с помощью malloc, должны быть возвращены в систему путем вызова free. После того, как вы позвоните free, вам больше не разрешат доступ к этой памяти.

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


Итак, почему вы все еще можете получить доступ к памяти, которая была освобождена? Ну, вы не можете надежно сделать это. Так уж получилось, что внедрение большинства систем управления памятью означает, что иногда вы можете избежать подобных злоупотреблений. Многие менеджеры памяти выделяют большие блоки памяти из операционных систем, а затем, в свою очередь, выделяют небольшие подблоки для приложения. Когда вы вызываете free, распределитель возвращает этот блок обратно в свой пул легкодоступной памяти, но не обязательно возвращает память обратно ОС, поскольку процедуры выделения памяти ОС обычно дороги. Следовательно, доступ к нему может все еще работать, потому что память все еще распределена в вашем процессе. Просто теперь он принадлежит менеджеру памяти, а не вашему приложению. Нечто подобное происходит с вами здесь.

Конечно, иногда вам не удастся избежать подобных нарушений, скорее всего, после того, как вы развернете свое программное обеспечение на компьютере самого важного клиента!

1 голос
/ 10 августа 2011

Обычно диспетчер памяти имеет что-то вроде связанного списка свободных блоков, которые используются для удовлетворения последующих выделений.

Вот минимальная реализация, которую я написал несколько лет назад. На самом деле он не предназначен (или не подходит) для серьезного использования, но дает хотя бы общее представление об одном способе управления кучей:

#include <stddef.h>

typedef struct node {
    size_t size;
    struct node *next;
} node;

node *free_list;

static void *split_end(node *block, size_t new_size) {
    size_t difference = block->size - new_size;

    node *temp = (node *)((char *)block + difference);
    temp->size = new_size;
    block->size = difference;
    return (void *)((size_t *)temp+1);
}

static void *split_begin(node *block, size_t new_size) {
    size_t difference = block->size-new_size;
    node *temp = (node *)((char *)block + new_size);
    temp->size = difference;
    temp->next = free_list;
    free_list = temp;
    return block;
}

void b_init(void *block, size_t block_size) {
    ((node *)block)->size = block_size - sizeof(node);
    ((node *)block)->next = NULL;
    free_list = block;
}

void b_free(void *block) {
    node *b = (node *)((size_t *)block -1);

    b->next = free_list;
    free_list = b;
}

void *b_malloc(size_t size) {
    node *temp, **ptr;
    size_t larger = size+sizeof(node);
    size += sizeof(size_t);

    for ( ptr = &free_list;
        NULL != ptr;
        ptr = &((*ptr)->next)) 
    {
        if ((*ptr)->size >= size) {
            if ( (*ptr)->size <= larger) {
                temp = (*ptr);
                (*ptr) = (*ptr)->next;
                return (void *)((size_t *)temp + 1);
            }
            else
                return split_end(*ptr, size);       
        }
    }
    return NULL;
}

void *b_realloc(void *block, size_t new_size) {
    node *b = (node *)((char *)block - sizeof(size_t));
    char *temp;
    size_t i, size;

    if ( new_size == 0) {
        b_free(block);
        return NULL;
    }

    new_size += sizeof(size_t);

    size = b->size;
    if ( new_size <size)
        size = new_size;

    size -= sizeof(size_t);

    if ( b->size >= new_size+sizeof(node *) )
        return split_begin(b, new_size);

    if ( b->size >= new_size)
        return b;

    temp = b_malloc(new_size);
    if ( NULL == temp)
        return NULL;

    for ( i=0; i<size;i++)
        temp[i] = ((char *)block)[i];
    b_free(block);
    return temp;
}

#ifdef TEST 
#define num 10

int main(void) {

    int i;
    char block[4096];
    char *temp[num];
    char *big;

    b_init(block, sizeof(block));

    big = b_malloc(100);

    for (i=0; i<num; i++)
        temp[i] = b_malloc(10);

    for (i=0; i<num; i++)
        b_free(temp[i]);

    b_realloc(big, 200);
    b_realloc(big, 10);
    b_realloc(big, 0);

    return 0;
}

#endif
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...