Каковы некоторые полезные примеры malloc() в C?

Я просто читаю о malloc() в C.

Статья в Википедии содержит example, однако он просто выделяет достаточно памяти для массива из 10 целых чисел по сравнению с int array[10]. Не очень полезно.

Когда вы решили использовать malloc() over C для обработки памяти для вас?

Ответы

Ответ 1

Динамические структуры данных (списки, деревья и т.д.) используют malloc для размещения своих узлов в куче. Например:

/* A singly-linked list node, holding data and pointer to next node */
struct slnode_t
{
    struct slnode_t* next;
    int data;
};

typedef struct slnode_t slnode;

/* Allocate a new node with the given data and next pointer */
slnode* sl_new_node(int data, slnode* next)
{
    slnode* node = malloc(sizeof *node);
    node->data = data;
    node->next = next;
    return node;
}

/* Insert the given data at the front of the list specified by a 
** pointer to the head node
*/
void sl_insert_front(slnode** head, int data)
{
    slnode* node = sl_new_node(data, *head);
    *head = node;
}

Рассмотрим, как новые данные добавляются в список с помощью sl_insert_front. Вам нужно создать node, в котором будут храниться данные и указатель на следующий node в списке. Где вы собираетесь его создать?

  • Возможно, на стек! - НЕТ - где будет выделено это пространство стека? В какой функции? Что происходит с ним, когда функция завершается?
  • Возможно, в статической памяти! - НЕТ - вам нужно заранее знать, сколько у вас узлов списка, поскольку статическая память предварительно распределена при загрузке программы.
  • В куче? ДА - потому что у вас есть все необходимые гибкости.

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

Ответ 2

Что делать, если вы не знаете размер массива при написании своей программы? В качестве примера можно представить, что вы хотите загрузить изображение. Сначала вы не знаете его размер, поэтому вам нужно будет прочитать размер из файла, выделить буфер с этим размером и затем прочитать файл в этом буфере. Очевидно, вы не могли бы использовать массив статического размера.

EDIT:

Еще один момент: при использовании динамического выделения память выделяется в куче, а массивы выделяются в стеке. Это очень важно, когда вы программируете встроенное устройство, поскольку стек может иметь ограниченный размер по сравнению с кучей.

Ответ 3

В приведенном ниже примере int array[10] исчезает, когда вы покидаете рамку стека. Если вы хотите, чтобы используемая память сохранялась за пределами локальной области, вы должны использовать malloc();

Ответ 4

Я рекомендую вам google Стек и куча.

int* heapArray = (int*)malloc(10 * sizeof(int));
int stackArray[10];

Оба очень похожи в том, как вы обращаетесь к данным. Они отличаются друг от друга тем, что данные хранятся за кулисами. HeapArray выделяется в куче и только отменяется, когда приложение умирает, или когда вызывается free(heapArray). Элемент stackArray выделяется в стеке и освобождается, когда пакет распаковывается.

Ответ 5

malloc() используется всякий раз, когда:

  • Вам нужно динамическое распределение памяти
    Если вам нужно создать массив размера n, где n вычисляется во время выполнения вашей программы, единственный способ сделать это - использовать malloc().

  • Вам нужно выделить память в куче Переменные, определенные в некоторых функциях, живут только до конца этой функции. Таким образом, если нужны некоторые "независимые от вызова" данные, он должен быть передан/возвращен как параметр функции (который не всегда подходит) или хранится в куче. Единственный способ хранения данных в куче - использовать malloc(). Существуют массивы с переменным размером, но они выделяются в стеке.

Ответ 6

Хотя вы можете делать массивы переменной длины с C99, по-прежнему нет достойной замены более динамических структур данных. Классическим примером является связанный список. Чтобы получить произвольный размер, вы используете malloc для выделения каждого node, чтобы вы могли вставлять и удалять без массивного копирования памяти, как это было бы с массивом переменной длины.

Например, стеки произвольного размера с использованием простого связанного списка:

#include <stdio.h>
#include <stdlib.h>

typedef struct sNode {
    int payLoad;
    struct sNode *next;
} tNode;

void stkPush (tNode **stk, int val) {
    tNode *newNode = malloc (sizeof (tNode));
    if (newNode == NULL) return;
    newNode->payLoad = val;
    newNode->next = *stk;
    *stk = newNode;
}

int stkPop (tNode **stk) {
    tNode *oldNode;
    int val;
    if (*stk == NULL) return 0;
    oldNode = *stk;
    *stk = oldNode->next;
    val = oldNode->payLoad;
    free (oldNode);
    return val;
}

int main (void) {
    tNode *top = NULL;
    stkPush (&top, 42);
    printf ("%d\n", stkPop (&top));
    return 0;
}

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