Тарифы Услуги Сим-карты

Распределение памяти: malloc() и са11ос(). Массивы Как работает malloc


#include void *malloc(size_t size);

Описание


Возвращает указатель на первый байт области памяти, которая была выделена из кучи


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

Если вы пишете 16-разрядные программы для семейства процессоров 8086(например, 80486 или Pentium), то ваш компилятор, вероятно, предоставляет дополнительные функции выделения памяти, которые учитывают модель сегментированной памяти, используемую этими процессорами при работе в 16-разрядном режиме. Например, это могут быть функции, выделяющие память FAR-кучи(которая находится вне стандартного сегмента данных). Эти функции могут назначать указатели на память, объем которой больше одного сегмента, и освобождать такую память.

Динамическое выделение памяти

Основные проблемы применения

Нулевой указатель

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

·В языках C# и Java: null

·В языках Си и C++: 0 или макрос NULL. Кроме того, в стандарте C++11 для обозначения нулевого указателя предложено новое ключевое слово nullptr

·В языках Паскаль и Ruby: nil

·В языке Компонентный Паскаль:NIL

·В языке Python: None

Указателями сложно управлять. Достаточно легко записать в указатель неправильное значение, что может вызвать трудно воспроизводимую ошибку. Например, вы случайно поменяли адрес указателя в памяти, или неправильно выделили под информацию память и тут вас может ожидать сюрприз: другая очень важная переменная, которая используется только внутри программы будет перезаписана. В таком случае вам будет сложно воспроизвести баг. Нелегко будет и понять, где именно находится ошибка. И не всегда тривиально будет её устранить (иногда придётся переписать существенную часть программы).

Для решения части проблем есть методы предохранения и страховки:

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

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

Так как различные типы данных имеют разные требования к памяти, мы как-то должны научиться получить размер в байтах для данных разного типа. Например, нам нужен участок памяти под массив значений типа int - это один размер памяти, а если нам нужно выделить память под массив того же размера, но уже типа char - это другой размер. Поэтому нужно как-то вычислять размер памяти. Это может быть сделано с помощью операции sizeof(), которая принимает выражение и возвращает его размер. Например, sizeof(int) вернет количество байтов, необходимых для хранения значения типа int. Рассмотрим пример:


Яндекс.Директ


#include int *ptrVar = malloc(sizeof(int));

В этом примере, встроке 3 указателю ptrVar присваивается адрес на участок памяти, размер которого соответствует типу данных int. Автоматически, этот участок памяти становится недоступным для других программ. А это значит, что после того, как выделенная память станет ненужной, её нужно явно высвободить. Если же память не будет явно высвобождена, то по завершению работы программы, память так и не освободится для операционной системы, это называется утечкой памяти. Также можно определять размер выделяемой памяти, которую нужно выделить передавая пустой указатель, вот пример:



Как видите, в такой записи есть одна очень сильная сторона, мы не должны вызывать функцию malloc() с использованиемsizeof(float). Вместо этого мы передали в malloc() указатель на тип float, в таком случае, размер выделяемой памяти автоматически определится сам!

Особенно это пригодится, если выделять память потребуется далеко от определения указателя:


float *ptrVar; /* . . . сто строк кода */ . . . ptrVar = malloc(sizeof(*ptrVar));

Если бы вы использовали конструкцию выделения памяти с операцией sizeof(), то вам бы пришлось находить в коде определение указателя, смотреть его тип данных и уже потом вы бы смогли правильно выделить память.

Описание функций

#include void * malloc (size_t size) ; void * calloc (size_t num, size_t size) ;

Назначение

malloc принимает в качестве аргумента размер выделяемой области в байтах ; возвращает нетипизированный указатель (void*) на область памяти заявленного размера или NULL в случае, если выделить память невозможно. Содержимое выделяемой области памяти не определено.

calloc принимает в качестве аргумента количество элементов и размер каждого элемента в байтах; возвращает нетипизированный указатель (void*) на область памяти заявленного размера или NULL в случае, если выделить память невозможно. Значения элементов устанавливаются в ноль. malloc работает быстрее, чем calloc , в связи с отсутствием функции обнуления выделяемой памяти.

Параметры функций

malloc

  • size - размер распределяемой области памяти

calloc

  • num - количество распределяемых элементов
  • size - размер каждого элемента

Возвращаемое значение

Функции возвращают нетипизированный (void*) указатель на область памяти в случае успеха, либо NULL в противном случае.

Характерные ошибки при использовании

  • Память остаётся «занятой», даже если ни один указатель в программе на неё не ссылается (для освобождения памяти используется функция free()). Накопление «потерянных» участков памяти приводит к постепенной деградации системы. Ошибки, связанные с неосвобождением занятых участков памяти, называются утечками памяти (англ. memory leaks ).
  • Если объём обрабатываемых данных больше, чем объём выделенной памяти, возможно повреждение других областей динамической памяти. Такие ошибки называются ошибками переполнения буфера (англ. buffer overflow ).
  • Если указатель на выделенную область памяти после освобождения продолжает использоваться, то при обращении к «уже не существующему» блоку динамической памяти может произойти исключение (англ. exception ), сбой программы, повреждение других данных или не произойти ничего (в зависимости от типа операционной системы и используемого аппаратного обеспечения).
  • Если для одной области памяти free() вызывается более чем один раз, то это может повредить данные самой библиотеки , содержащей malloc/free, и привести к непредсказуемому поведению в произвольные моменты времени.
  • Неудачная организация программы, в которой выделяется и освобождается множество небольших объёмов памяти - возможна фрагментация свободной памяти («пунктир»), при которой свободной памяти в сумме остаётся много, но выделить большой кусок невозможно.

Точное поведение функций описано в стандарте ANSI C , на него же ссылается определение функции в стандарте POSIX .

Примеры использования

malloc

Float * dynamic_array = malloc(number_of_elements * sizeof (float ) ) ; if (! dynamic_array) { }

calloc

Float * dynamic_array = calloc(number_of_elements, sizeof (float ) ) ; if (! dynamic_array) { /* обработка ошибки выделения памяти */ } /* … работа с элементами массива … */ free(dynamic_array) ; dynamic_array = NULL;

См. также

  • stdlib
  • alloca
  • soap malloc
  • soap destroy

Источники

  • malloc (англ.) . - Описание функции malloc в стандарте POSIX.
  • calloc (англ.) . - Описание функции calloc в стандарте POSIX.

Wikimedia Foundation . 2010 .

Смотреть что такое "Malloc" в других словарях:

    Malloc - est en informatique une fonction de la bibliothèque standard du C permettant d allouer dynamiquement de la mémoire. La libération de la mémoire ainsi réservée s effectue avec la fonction free. Cette fonction est déclarée dans le fichier d en tête … Wikipédia en Français

    malloc - est en informatique une fonction de la bibliothèque standard de C permettant d allouer dynamiquement de la mémoire. La libération de la mémoire ainsi réservée s effectue avec la fonction free. Cette fonction est déclarée dans l en tête

    Malloc - In computing, malloc is a subroutine provided in the C and C++ programming language s standard libraries for performing dynamic memory allocation. Rationale The C programming language manages memory either statically or automatically . Static… … Wikipedia

    Malloc - En informática, malloc es una subrutina para el ejercicio de asignación de memoria dinámica en los lenguajes de programación C y C++. Es una abreviatura del inglés Memory Allocation. Forma parte de la biblioteca estándar stdlib.h para ambos… … Wikipedia Español

    malloc - 1. noun A subroutine in the C programming languages standard library for performing dynamic memory allocation. It compares the behavior of nine different mallocs when used with Hummingbird and GNU Emacs dynamic memory activity traces. 2. verb … Wiktionary

    malloc - ● np. cde. LANGC CMDE Contraction de Memory Allocation. Nom d une fonction très importante de la bibliothèque C, car elle permet d attribuer une partie de la mémoire à un processus. Voir aussi calloc. (D après ) … Dictionnaire d"informatique francophone

    C dynamic memory allocation - C Standard Library Data types Character classification Strings Mathematics File input/output Date/time Localization … Wikipedia

    Pointer (computing) - This article is about the programming data type. For the input interface (for example a computer mouse), see Pointing device. Pointer a pointing to the memory address associated with variable b. Note that in this particular diagram, the computing … Wikipedia

    Значимость предмета статьи поставлена под сомнение. Пожалуйста, покажите в статье значимость её предмета, добавив в неё доказательства значимости по частным критериям значимости или, в случае если частные критерии значимости для… … Википедия

    Dangling pointer - Dangling pointers and wild pointers in computer programming are pointers that do not point to a valid object of the appropriate type. These are special cases of memory safety violations. Dangling Pointer Dangling pointers arise when an object is… … Wikipedia

  • описать указатель (тип * указатель; );
  • определить размер массива;
  • выделить участок памяти для хранения массива и присвоить указателю адрес этого участка памяти.

Для выделения памяти в С++ можно воспользоваться оператором new или функциями языка С - calloc, malloc, realloc . Все функции находятся в библиотеке stdlib.h .

5.2.1 Функция malloc

Функция malloc выделяет непрерывный участок памяти размером size байт и возвращает указатель на первый байт этого участка. Обращение к функции имеет вид:

void* malloc (size_t size);

где size - целое беззнаковое значение 1size_t - базовый беззнаковый целочисленный тип языка С/С++, который выбирается таким образом, чтобы в него можно было записать максимальный размер теоретически возможного массива любого типа. В 32-битной операционной системе size_t является беззнаковым 32-битным числом (максимальное значение 2 32 - 1), в 64-битной - 64-битным беззнаковым числом (максимальное значение 2 64 - 1). , определяющее размер выделяемого участка памяти в байтах. Если резервирование памяти прошло успешно, то функция возвращает переменную типа void* , которую можно преобразовать к любому необходимому типу указателя. Если выделить память невозможно, то функция вернёт пустой указатель NULL .

Например,

double *h; //Описываем указатель на double. int k; cin>>k; //Ввод целого числа k. //Выделение участка памяти для хранения k элементов типа double. //Адрес этого участка хранится в переменной h. h=(double *) malloc (k* sizeof (double)); //h - адрес начала участка памяти, //h + 1, h + 2, h + 3 и т. д. - адреса последующих элементов типа double

5.2.2 Функция calloc

Функция calloc предназначена для выделения и обнуления памяти.

void * calloc (size_t num, size_t size);

С помощью функции будет выделен участок памяти, в котором будет храниться num элементов по size байт каждый. Все элементы выделенного участка обнуляются. Функция возвращает указатель на выделенный участок или NULL при невозможности выделить память.

Например,

float *h; //Описываем указатель на float. int k; cin>>k; //Ввод целого числа k. //Выделение участка памяти для хранения k элементов типа float. //Адрес этого участка хранится в переменной h . h=(float *) calloc (k, sizeof (float)); //h - адрес начала участка памяти, //h + 1, h + 2, h + 3 и т. д. - адреса последующих элементов типа float.

5.2.3 Функция realloc

Функция realloc изменяет размер ранее выделенного участка памяти. Обращаются к функции так:

void *realloc (void *p, size_t size);

где p - указатель на область памяти, размер которой нужно изменить на size . Если в результате работы функции меняется адрес области памяти, то новый адрес вернётся в качестве результата. Если фактическое значение первого параметра NULL , то функция realloc работает так же, как и функция malloc , то есть выделяет участок памяти размером size байт.

5.2.4 Функция free

Для освобождения выделенной памяти используется функция free . Обращаются к ней так:

void free (void *p);

где p - указатель на участок памяти, ранее выделенный функциями malloc, calloc или realloc .

5.2.5 Операторы new и delete

В языке С++ есть операторы new для выделения и delete для освобождения участка памяти.

Для выделения памяти для хранения n элементов одного типа оператор new имеет вид [

Динамическое выделение памяти с помощью библиотечной функции malloc состоит из следующих шагов.

1. Включение в программу файла заголовков malloc .h директивой #include .

2. Объявление указателя нужного типа, например int *p ;

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

p =(int *) malloc (число элементов массива*sizeof (int ));

Вместо int может быть подставлен любой стандартный или введенный программистом тип.

4. Проверка факта выделения памяти. Если выделение памяти в нужном объеме невозможно, функция malloc возвращает в качестве своего результата нулевой указатель NULL , соответствующий значению ложь. Если выделение памяти выполнено, продолжаем выполнение программы, если нет, выходим из нее с соответствующей диагностикой о недостатке памяти. Пример:

if (!p ) сообщение, выход; else продолжение;

5. Освобождение памяти после окончания работы с ней. Для этого вызываем функцию f гее и используем указатель в качестве аргумента:

free (p );

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

Наиболее частой причиной «зависания» компьютера при работе с динамически выделяемой памятью является несоответствие инструкций malloc и free (в обеих инструкциях должен использоваться один и тоже указатель) или недостаточный объем свободной памяти.

В качестве примера рассмотрим ввод/вывод одномерного динамического массива произвольной длины, задаваемой с клавиатуры.

int i ,n ,*massiv ;//объявление указателя

cout <>n ;//ввод размера массива

massiv=(int*)malloc(n*sizeof(int));//выделение динам.памяти

if (!massiv )//проверка факта выделения памяти

{cout <

cout <

getch();

return 0;}

cout<

for(i=0;i>massiv[i];//ввод массива

cout<

for(i=0;i

free (massiv );//освобождение памяти

В этой программе указатель используется только для выделения динамической памяти. Далее в программе обращение к элементам массива осуществляется через имя массива, которое совпадает с именем указателя.

Для динамического выделения памяти можно также использовать функцию calloc (). В отличии от malloc функция calloc кроме выделения области памяти под массив объектов еще производит инициализацию элементов массива нулевыми значениями.

В зависимости от используемой версии C++ для работы с большими фрагментами динамической памяти возможно применение функций farmalloc (), farcalloc (), farcoreleft () и farfree ().