Каковы некоторые полезные примеры malloc () в C? - PullRequest
14 голосов
/ 03 ноября 2010

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

В статье Википедии приведен пример , однако он оправдывает выделение достаточного объема памяти для массива 10 дюймов по сравнению с int array[10]. Не очень полезно.

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

Ответы [ 6 ]

19 голосов
/ 03 ноября 2010

Динамические структуры данных (списки, деревья и т. Д.) Используют 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. Вам необходимо создать узел, который будет содержать данные и указатель на следующий узел в списке. Где вы собираетесь его создать?

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

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

4 голосов
/ 03 ноября 2010

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

EDIT:

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

2 голосов
/ 03 ноября 2010

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

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

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

2 голосов
/ 03 ноября 2010

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

1 голос
/ 03 ноября 2010

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

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

#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, есть лучшие способы сделать это.

1 голос
/ 03 ноября 2010

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

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

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

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