Malloc/calloc выделяет уже выделенный адрес

Я пытался отлаживать это часами.


У меня есть структура планировщика.

typedef struct rr_scheduler {
    unsigned int time_q;
    unsigned int avg_wait;
    unsigned int avg_turnaround;
    unsigned int processes_served;
    unsigned int t;
    unsigned int next_dispatch_t;
    Process* cp;
    LinkedList* queue;
    LinkedList* done_list;
} rr_scheduler;

Он инициализируется так:

rr_scheduler* new_rr_scheduler(unsigned int time_q) {
    rr_scheduler* rr = NULL;

    rr = (rr_scheduler*)malloc(sizeof rr);

    rr->time_q = time_q;
    rr->queue = newLinkedList();
    rr->done_list = newLinkedList();
    rr->avg_wait = 0;
    rr->avg_turnaround = 0;
    rr->processes_served = 0;
    rr->t = 0;
    rr->next_dispatch_t = 0;
    rr->cp = NULL;

    return rr;
}

Вот функция инициализации linkedList. (Да, я знаю, что мне не нужно устанавливать нулевые значения, если я использую calloc)

LinkedList* newLinkedList() {
    LinkedList* newList = (LinkedList*)calloc(1, sizeof (LinkedList));
    newList->head = NULL;
    newList->tail = NULL;
    newList->current = NULL;
    newList->length = 0;
    return newList;
}

Потратив на это целую вечность, я заметил, что две несвязанные переменные изменились одновременно. Оказывается, scheduler->cp и scheduler->queue->tail имеют один и тот же адрес памяти.

Изображение одного и того же адреса

Здесь s — это указатель rr_scheduler.

Буду очень признателен за любые возможные причины этого.


person scradam    schedule 13.05.2014    source источник
comment
Инициализация данных в NULL/0 не требуется после calloc(), но, возможно, вы добавили это только сейчас для ясности.   -  person Yirkha    schedule 13.05.2014


Ответы (1)


sizeof rr

это размер указателя. Но вам нужно выделить достаточно памяти для структуры. Использовать

sizeof *rr

or

sizeof(rr_scheduler)

сделать это.

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

Также кажется странным инициализировать rr значением NULL, а затем сразу присваивать ему значение. я бы написал так

rr_scheduler* rr = malloc(sizeof *rr);
person David Heffernan    schedule 13.05.2014
comment
Я бы сделал sizeof (struct rr_scheduler), но в любом случае он не выделяет достаточно памяти. - person ojblass; 13.05.2014
comment
@ojblass sizeof *rr лучше, потому что вам не нужно дублировать имя типа, что приводит к более удобному и понятному коду. - person Filipe Gonçalves; 13.05.2014
comment
@FilipeGonçalves Это спорно. Вместо дублирования имени типа вы дублируете имя переменной. - person David Heffernan; 13.05.2014
comment
Конечно, но дублировать имя переменной не так плохо, как делать это для имени типа. Взгляните на stackoverflow.com /вопросы/373252/ - person Filipe Gonçalves; 13.05.2014
comment
@FilipeGonçalves Хорошо, может быть, вы правы. Но нужно хотя бы немного подумать об этом. Чего я явно не делал! ;-) - person David Heffernan; 13.05.2014
comment
Если вы используете имя переменной, вы можете изменить ее тип, не нарушая malloc() - person JeremyP; 13.05.2014
comment
Отличный ответ, у меня тоже было несколько других случаев такой же проблемы! Остаточный нулевой код инициализации был очищен, и все работает отлично. - person scradam; 13.05.2014