C - управление памятью - PullRequest
       0

C - управление памятью

1 голос
/ 20 марта 2011

Я только что написал код C:

#include <stdlib.h>
#include <time.h>
#include <string.h>

typedef struct {
    void **data;
    time_t lastModified;
} container;

container *container_init() {
    container *c = malloc(sizeof(container));
    void *data = NULL;
    c->data = &data;
    c->lastModified = time(NULL);
    return c;
}

void *container_getData(container *c) {
    void **containerData = c->data;
    return *containerData;
}

// only pass manually allocated data that can be free()'d!
void container_setData(container *c, void *data) {
    free(container_getData(c));
    c->data = &data;
}

void container_free(container *c) {
    free(container_getData(c)); // <--- THIS LINE
    free(c);
}

int main(int argc, const char *argv[]) {
    for (int i = 0; i < 100000000; i++) {
        char *data = strdup("Hi, I don't understand pointers!");
        container *c = container_init();
        container_setData(c, data);
        container_free(c);
    }
}

Моя логика была следующей: когда я вызываю container_setData(), старые данные имеют значение free() 'd, и указатель на новые данные сохраняется. Эти новые данные должны будут быть выпущены в какой-то момент. Это происходит в последний раз во время звонка на container_free().

Я отметил линию в функции container_free(). Я бы поклялся, что мне понадобится эта строка, чтобы предотвратить утечку памяти. Тем не менее, я не могу использовать строку («объект был освобожден не был выделен»), и нет никакой утечки памяти, если я ее удаляю. Как освобождается строка из моего цикла?!

Может кто-нибудь объяснить, где ошибка?

Ответы [ 2 ]

3 голосов
/ 20 марта 2011
c->data = &data;

хранит адрес указателя data (аргумент вашей функции), а не фактический указатель. То есть, вы храните указатель на временный.

Вы могли бы построить структуру container только с членом void *data.

1 голос
/ 20 марта 2011

Чтобы объяснить ответ larsmans с помощью кода, внесите следующие изменения:

typedef struct {
    void *data;
    time_t lastModified;
} container;


void *container_getData(container *c) {
   return c->data;
}

void container_setData(container *c, void *data) {
    free(c->data);
    c->data = data;
}

void container_free(container *c) {
    free(c->data); 
    free(c);
}

И другие изменения тоже - это просто приведет вас на правильный путь.

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