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

Я пытаюсь создать очень простой блокчейн для дидактических целей.Каждый блок содержит различные простые переменные и структурные переменные.Блокчейн - это простой массив блоков.

#define BLOCKCHAIN_MAX_SIZE 1000

struct transaction{ 
    struct sockaddr_in sender_ip_port;
    int quantity;
    struct sockaddr_in receiver_ip_port;
    int randomNumber;
};

struct block { 
    int index;
    long timestamp;
    struct transaction transaction;
    int waitTime;
};

int main(int argc, char *argv[]) {
    struct block **blockchain = malloc(sizeof(struct block *) * BLOCKCHAIN_MAX_SIZE);
    blockchain[0]=malloc(sizeof(struct block));
    blockchain[0]->index = 0;
    blockchain[0]->waitTime= 0;
    blockchain[0]->timestamp = 1549035455; 
    blockchain[0]->transaction.quantity= 0;
    blockchain[0]->transaction.randomNumber= 0;

    struct block *newBlock= (struct block *)malloc(sizeof(struct block));
    //Fill up the new block with data

    blockchain[1]=malloc(sizeof(struct block));
    blockchain[1] = newBlock;
}

это правильно?

Большое спасибо

1 Ответ

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

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

Ваш двойной указатель на struct block **blockchain может быть хорошим выбором или нет, в зависимости от того, хотите ли вы все blockchain[i]данные смежные.Если вы используете отдельные malloc для каждого элемента, вы можете страдать от фрагментации памяти.

Как говорит нм, blockchain[1] = malloc, за которым следует blockchain[1] = newBlock, определенно неверно.Вы хотите либо ту же стратегию, что и с blockchain[0], либо просто подтолкнуть вещи к newBlock, а затем blockchain[1] = newBlock: здесь вы просто назначаете указатели, а не значения.

Тем не менее, ваш «подобный блокчейну»Структура может содержать только одну транзакцию на блок.Как правило, вам нужно варьировать количество транзакций.Поскольку в массивах C нет встроенного счетчика длины (это просто непрерывное пространство памяти), вам придется изменить определение блока на что-то вроде этого:

struct block { 
    int index;
    long timestamp;
    int waitTime;
    int transactions_len;
    struct transaction transactions[];
};

Таким образом, вы можетевыделить блок переменной длины, который может иметь различную длину в зависимости от блока.Смежный вопрос: выделение элементов гибкого массива в виде структуры

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

Я не могу комментировать структуры sockaddr_in, так как не знаю, для чего вы их использовали бы.В зависимости от их жизненного цикла, вы можете захотеть сохранить их копию (как вы делаете) или просто указатели на них, но это будет зависеть от того, что вы хотите делать с данными и чью ответственность они должны изменить / освободить /изменить данные.

...