Как распределяется память для вложенных структур в C? - PullRequest
0 голосов
/ 10 июля 2019

Пару дней назад я задал этот вопрос .Я продублировал 90% кода, приведенного в ответе на мой предыдущий вопрос.Однако, когда я использовал Valgrind для выполнения memcheck, он сказал мне, что были утечки памяти.Но я не думаю, что разница в 10% привела к утечке памяти.В дополнение к проблеме утечки памяти у меня есть пара других вопросов.

Краткое резюме моего предыдущего поста: у меня есть многопоточная структура.Мне нужно правильно выделить память для него и освободить память позже.Структура всей структуры должна выглядеть следующим образом:

                          College Sys
           |           |           |      ...      |
        ColleA       ColleB      ColleC   ...     ColleX
    |  |  |  |    |  |  |  |   |  |  |  |  ...  |  |  |  |
   sA sB sC  sD  sA sB sC  sD sA sB sC  sD ... sA sB sC  sD
    |  |  |  |    |  |  |  |   |  |  |  |  ...  |  |  |  | 
   fam fam ...
// Colle is short for college
// s is short for stu (which is short for student)

Может быть произвольное количество колледжей и студентов, которое контролируется #define MAX_NUM _num_.Как и в предыдущем ответе, я должен выделить память в порядке «от крайнего к внутреннему» и освободить память «от самого внутреннего к внешнему».Я в основном понимаю логику за образец.Следующие вопросы являются дополнениями к нему.

1) Означает ли

CollegeSys -> Colle = malloc(sizeof(*(CollegeSys -> Colle)) * MAX_NUM);
CollegeSys -> Colle -> stu = malloc(sizeof(*(CollegeSys -> Colle -> stu)) * MAX_NUM);
CollegeSys -> Colle -> stu -> fam = malloc(sizeof(*(CollegeSys -> Colle -> stu -> fam)));

, что «в системе колледжей есть MAX_NUM колледжей, в каждом из которых есть MAX_NUM студентов - каждый изу которой одна семья "?

1.a) Если да, нужно ли мне для циклов , чтобы инициализировать каждое отдельное значение, содержащееся в этой огромной структуре?Например, возможно правильный путь:

for (int i = 0; i < MAX_NUM; i++) {
    strcpy(CollegeSys -> Colle[i].name, "collestr");
    for (int n = 0; n < MAX_NUM; n++) {
        strcpy(system -> Colle[i].stu[n].name, "stustr");
        ...
    }
}

возможно неправильный путь:

strcpy(CollegeSys -> Colle -> name, "collestr");
strcpy(CollegeSys -> Colle -> stu -> name, "stustr");

Я попробовал «возможно неправильный путь».Синтаксической ошибки не было, но она только инициализировала бы CollegeSys -> Colle[0].name и ... -> stu[0].name.Итак, второй подход, скорее всего, будет неправильным, если я захочу инициализировать каждый отдельный атрибут.

2) Если я весь этот процесс модульный, разделив процесс на несколько функций, которые возвращают соответствующие указатели структуры - newSystem(void), newCollege(void), newStudent(void) (аргументы не обязательно являются недействительными; мы могли бы также передать str как name функциям; кроме того, может быть ряд addStu() и т. Д.)присвойте эти возвращенные указатели соответствующей части CollegeSys).Когда я создаю новый CollegeSys в newSystem(), правильно ли раз и навсегда распределять память для каждой вложенной структуры в newSystem()?

2.a) Если я выделяю память для всех частей структурыв newSystem() возможное последствие, о котором я могу думать, это утечки памяти.Поскольку при создании системы мы выделили память всем частям, мы неизбежно должны создать новый указатель структуры и выделить ему достаточно памяти в двух других функциях.Например,

struct Student* newStudent(void) {
   struct Student* newStu = malloc(sizeof(struct Student));
   newStu -> fam = malloc(sizeof(*(newStu -> fam)));
   // I'm not sure if I'm supposed to also allocate memoty to fam struct
   ...
   return newStu;
}

Если это так, мы фактически выделяем один и тот же объем памяти для экземпляра как минимум дважды - один в newSystem(void), другой в newStudent(void).Если я пока прав, это определенно утечка памяти.И память, которую мы выделяем для указателя newStu в newStudent(void), никогда не может быть освобождена (я так думаю).Тогда каков правильный способ выделения памяти для всей структуры, когда мы разделяем весь процесс выделения памяти на несколько небольших шагов?

3) Должны ли мы использовать sizeof(*(layer1 -> layer2 -> ...)) при распределении памяти по структуре, вложенной в структуру?Можем ли мы напрямую указать его тип?Например, делая это

CollegeSys -> Colle = malloc(sizeof(struct College) * MAX_NUM);
// instead of 
// CollegeSys -> Colle = malloc(sizeof(*(CollegeSys -> Colle)) * MAX_NUM);

4) Кажется, даже если мы выделим определенное количество памяти для указателя, мы все равно не сможем предотвратить segfault.Например, мы кодируем

// this is not completely correct C code, just to show what I mean
struct* ptr = malloc(sizeof(struct type) * 3);

Мы все еще можем вызывать ptr[3], ptr[4] и т. Д., И компилятор выведет ерунду.Иногда компилятор может выдать ошибку, а иногда нет.Так что, по сути, мы не можем полагаться на malloc (или calloc и т. Д.), Чтобы избежать появления segfault?

Извините за написание такого длинного текста.Спасибо за ваше терпение.

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