Когда я должен использовать malloc для выделения памяти?

1)
Для которых типов данных я должен выделить память с malloc?

  • Для типов как структуры, указатели, кроме основных типов данных, как интервал
  • Для всех типов?

2)
Почему я могу выполнить этот код? Почему это не отказывает? Я предположил, что должен выделить память для структуры сначала.

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

typedef unsigned int uint32;
typedef struct 
{
  int a;
  uint32* b;
}
foo;

int main(int argc, char* argv[])
{
 foo foo2;
 foo2.a = 3;
 foo2.b = (uint32*)malloc(sizeof(uint32));
 *foo2.b = 123;
}

Не был бы это быть лучше использовать

foo* foo2 = malloc(sizeof(foo));

3) Как foo.b установлен? Ссылочная случайная память или ПУСТОЙ УКАЗАТЕЛЬ?

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

typedef unsigned int uint32;
typedef struct 
{
  int a;
  uint32* b;
}
foo;

int main(int argc, char* argv[])
{
 foo foo2;
 foo2.a = 3;

}
10
задан citronas 4 July 2010 в 19:10
поделиться

7 ответов

Отредактируйте, чтобы ответить на ваши пронумерованные вопросы.

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

  2. В вашем коде все в порядке - строка:

     foo foo2;
    

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

  3. В вашем примере в №3 значение foo2.b не определено. Любая автоматическая переменная имеет неопределенное и неопределенное значение, пока вы явно не инициализируете ее.

9
ответ дан 3 December 2019 в 14:10
поделиться

Вы должны выделить с помощью malloc любую память, которой вы хотите управлять вручную, а не автоматически. Неважно, хранится ли там int или double или struct или что-либо еще; malloc - это все для ручного управления памятью.

Когда вы создаете переменную без malloc, она хранится в стеке, и когда она выходит из области видимости, ее память автоматически восстанавливается. Переменная выходит из области видимости, когда к ней больше нет доступа; например, когда завершается блок или функция, в которой была объявлена переменная.

Когда вы выделяете память с помощью malloc, она хранится на куче, а malloc возвращает указатель на эту память. Эта память не будет возвращена, пока вы не вызовете free, независимо от того, остается ли указатель на нее доступным (когда указателей на память, выделенную из кучи, не остается, это утечка памяти). Это означает, что вы получаете возможность продолжать использовать выделенную вами память после завершения блока или функции, в которой она была выделена, но, с другой стороны, вы теперь обязаны вручную деаллоцировать ее, когда закончите с ней работать.

В вашем примере foo2 находится в стеке и будет автоматически деаллоцирована после завершения main. Однако память, на которую указывает foo2.b, не будет автоматически деаллоцирована, поскольку она находится на куче. Это не является проблемой в вашем примере, поскольку вся память возвращается в ОС при завершении программы, но если бы это было в функции, отличной от main, это было бы утечкой памяти.

3
ответ дан 3 December 2019 в 14:10
поделиться

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

18
ответ дан 3 December 2019 в 14:10
поделиться

2) Почему я могу запустить этот код? Почему не происходит сбой?

Код никогда не ссылается на неопределенную память или NULL. Почему он рухнет? (У вас есть утечка памяти, как написано, но это, вероятно, потому, что вы показываете только часть кода, и в данной программе это все равно не проблема.)

Альтернативный код, который вы предлагаете, также будет работать, хотя память, возвращенная из malloc также не инициализирован по умолчанию. (Однажды я работал с настраиваемым распределителем памяти, который по умолчанию заполнял возвращаемые блоки памяти символами ? . Все еще совершенно законно по правилам. Обратите внимание, что calloc возвращает указатель на память с нулевой инициализацией ; используйте его, если хотите.)

3) Как устанавливается foo.b ? Это ссылочная случайная память или NULL?

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

2
ответ дан 3 December 2019 в 14:10
поделиться

Вы можете это сделать, но этого недостаточно.

Потому что второе поле - это указатель, который должен быть установлен на действительный адрес. Один из способов сделать это - выделение памяти (с помощью malloc).

На ваш первый вопрос - используйте malloc, когда вы ДОЛЖНЫ управлять временем жизни объекта вручную.

Например, второй код можно переписать так:

int main(int argc, char* argv[])
{
 foo foo2; uint32 b;
 foo2.a = 3;
 foo2.b = &b;
 *foo2.b = 123;
}

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

1
ответ дан 3 December 2019 в 14:10
поделиться

foo foo2; автоматически выделяет структуру в стеке, и она автоматически освобождается, когда закрывающая функция (в данном случае main ) завершается.

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

2
ответ дан 3 December 2019 в 14:10
поделиться

Память для экземпляра структуры ("foo2") будет выделена в стеке - нет необходимости выделять для этого память самостоятельно - если вы выделяете память с помощью malloc, обязательно освободите память на более поздний срок.

1
ответ дан 3 December 2019 в 14:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: