Использование массива char для заполнения структуры в C - PullRequest
0 голосов
/ 24 марта 2019

Я пишу простой интерпретатор в C, и я не хочу иметь дело с управлением памятью, поэтому я пишу простой пул памяти, чтобы отслеживать и уменьшать количество malloc и free.

typedef struct object {

    Type type;
    char data[128];
    struct object* next;

} Object;

typedef struct pool {

    Object* head;
    unsigned int used;
    Object* blocks;

} Pool;

Как видите, мой пул памяти в настоящее время представляет собой просто связанный список «Объектов», и каждый объект имеет размер 128 байт.

Мои функции init и malloc приведены ниже:

#define BLOCK_COUNT 256

void* mp_init() {

    Pool* mp = malloc(1 * sizeof(Pool));

    mp->blocks = malloc(BLOCK_COUNT * sizeof(Object));

    mp->head = mp->blocks;
    mp->blocks->next = NULL;
    mp->used = 0;

    return mp;

}

void* mp_malloc(Pool* mp) {

    Object* obj = NULL;
    obj = (mp->blocks + mp->used);
    obj->next = (mp->blocks + (mp->used + 1) );
    obj->next->next = NULL;

    mp->used++;

    return obj;

}

Я использую char data[128], чтобы все мои объекты имели размер 128 байт, и моя функция malloc возвращает адрес каждого объекта, и я сохраняю все, что я хочу, в этих 128 байтах. Это плохая практика? Кажется странным просто использовать массив для увеличения размера структуры.

Ответы [ 2 ]

0 голосов
/ 24 марта 2019

Можно выделять всю память, которая нужна вашему приложению во время инициализации, если:

  1. Вы не хотите, чтобы ваши вызовы malloc не выполнялись из-за недостатка памяти во время выполнения.(Это может быть редкий сценарий, но ваше приложение должно быть достаточно устойчивым, чтобы справиться с ним)

  2. Ваше приложение не может допустить задержки, вызванные системными вызовами, такими как malloc и free.

Является ли это хорошей практикой или нет, зависит от типа приложения, над которым вы работаете.Из фрагмента кода, который вы опубликовали, я хотел бы дать пару комментариев:

  1. Конечно, вы должны реализовать свой собственный вызов mp_free, чтобы вернуть освобожденный блок обратно в пул памяти.

  2. Если ваше приложение освобождает блок в середине списка, ваш mp_malloc сможет его повторно использовать.

  3. Если все ваши потокиобращаясь к одному и тому же пулу памяти, вы должны убедиться, что вызовы mp_malloc и mp_free сделаны потокобезопасными.

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

0 голосов
/ 24 марта 2019

Я бы посчитал ваш код плохой практикой.

  1. Вам не нужен связанный список, если у вас есть массив (блоки).
  2. Вызов malloc(BLOCK_COUNT * sizeof(Object)); в вашем методе initвыделит все блоки.Это заставит вашу программу выделять всю необходимую память в начале, что может быть пустой тратой памяти, если вы точно не знаете, сколько памяти вам понадобится.
  3. Вам все равно придется управлять памятьюв вашем пуле, так что нет смысла его иметь.

Что вы можете сделать, это написать сборщик мусора.Это, однако, не тривиально и потребует много времени, чтобы объяснить здесь.

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

В противном случае, кто вы естьвероятно, ищет массивы "вариантов", которые имеют вид:

enum type {
    TYPE_1,
    ...
};

struct Object {
    enum type t;
    union {
       type_1 t1;
       ...
    };
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...