У вас вопросы?
У нас ответы:) SamZan.net

это массив байтов каждый байт имеет адрес начиная с нуля

Работа добавлена на сайт samzan.net:

Поможем написать учебную работу

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

Предоплата всего

от 25%

Подписываем

договор

Выберите тип работы:

Скидка 25% при заказе до 28.12.2024

Работа с памятью

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

Статическая память

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

Существует два типа статических переменных:

  1.  глобальные переменные - это переменные, определенные вне функций, в описании которых отсутствует слово static. Обычно описания глобальных переменных, включающие слово extern, выносятся в заголовочные файлы (h-файлы). Слово extern означает, что переменная описывается, но не создается в данной точке программы. Определения глобальных переменных, т.е. описания без слова extern, помещаются в файлы реализации (c-файлы или cpp-файлы). Пример: глобальная переменная maxind описывается дважды:
  2.  в h-файле с помощью строки
  3.  extern int maxind;

это описание сообщает о наличии такой переменной, но не создает эту переменную!

  1.  в cpp-файле с помощью строки
  2.  int maxind = 1000;

это описание создает переменную maxind и присваивает ей начальное значение 1000. Заметим, что стандарт языка не требует обязательного присвоения начальных значений глобальным переменным, но, тем не менее, это лучше делать всегда, иначе в переменной будет содержаться непредсказуемое значение (мусор, как говорят программисты). Инициализация всех глобальных переменных при их определении - это правило хорошего стиля.

  1.  Глобальные переменные называются так потому, что они доступны в любой точке программы во всех ее файлах. Поэтому имена глобальных переменных должны быть достаточно длинными, чтобы избежать случайного совпадения имен двух разных переменных. Например, имена x или n для глобальной переменной не подходят;
  2.  статические переменные - это переменные, в описании которых присутствует слово static. Как правило, статические переменные описываются вне функций. Такие статические переменные во всем подобны глобальным, с одним исключением: область видимости статической переменной ограничена одним файлом, внутри которого она определена, - и, более того, ее можно использовать только после ее описания, т.е. ниже по тексту. По этой причине описания статических переменных обычно выносятся в начало файла. В отличие от глобальных переменных, статические переменные никогда не описываются в h-файлах (модификаторы extern и static конфликтуют между собой). Совет: используйте статические переменные, если нужно, чтобы они были доступны только для функций, описанных внутри одного и того же файла. По возможности не применяйте в таких ситуациях глобальные переменные, это позволит избежать конфликтов имен при реализации больших проектов, состоящих из сотен файлов.
  3.  Статическую переменную можно описать и внутри функции, хотя обычно так никто не делает. Переменная размещается не в стеке, а в статической памяти, т.е. ее нельзя использовать при рекурсии, а ее значение сохраняется между различными входами в функцию. Область видимости такой переменной ограничена телом функции, в которой она определена. В остальном она подобна статической или глобальной переменной. Заметим, что ключевое слово static в языке Си используется для двух различных целей:
    1.  как указание типа памяти: переменная располагается в статической памяти, а не в стеке;
    2.  как способ ограничить область видимости переменной рамками одного файла (в случае описания переменной вне функции).
  4.  Слово static может присутствовать и в заголовке функции. При этом оно используется только для того, чтобы ограничить область видимости имени функции рамками одного файла. Пример:
  5.  static int gcd(int x, int y);  // Прототип ф-ции
  6.  . . .
  7.  static int gcd(int x, int y) { // Реализация
  8.      . . .
  9.  }

Совет: используйте модификатор static в заголовке функции, если известно, что функция будет вызываться лишь внутри одного файла. Слово static должно присутствовать как в описании прототипа функции, так и в заголовке функции при ее реализации.

Стековая, или локальная, память

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

Локальные переменные можно использовать при рекурсии, поскольку при повторном входе в функцию в стеке создается новый набор локальных переменных, а предыдущий набор не разрушается. По этой же причине локальные переменные безопасны при использовании нитей в параллельном программировании. Программисты называют такое свойство функции реентерабельностью, от англ.re-enter able - возможность повторного входа. Это очень важное качество с точки зрения надежности и безопасности программы! Программа, работающая со статическими переменными, этим свойством не обладает, поэтому для защиты статических переменных приходится использовать механизмы синхронизации, а логика программы резко усложняется. Всегда следует избегать использования глобальных и статических переменных, если можно обойтись локальными.

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

Динамическая память, или куча

Помимо статической и стековой памяти, существует еще практически неограниченный ресурс памяти, которая называется динамическая, или куча (heap). Программа может захватывать участки динамической памяти нужного размера. После использования ранее захваченный участок динамической памяти следует освободить.

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

адрес

содержимое памяти

0

4

8

код программы и данные,

защищенные от изменения

...

статические переменные

программы

динамическая память

max.

адрес

(232-4)

стек 

Структура динамической памяти автоматически поддерживается исполняющей системой языка Си или C++. Динамическая память состоит из захваченных и свободных сегментов, каждому из которых предшествует описатель сегмента. При выполнении запроса на захват памяти исполняющая система производит поиск свободного сегмента достаточного размера и захватывает в нем отрезок требуемой длины. При освобождении сегмента памяти он помечается как свободный, при необходимости несколько подряд идущих свободных сегментов объединяются.

В языке Си для захвата и освобождения динамической памяти применяются стандартные функции malloc и free, описания их прототипов содержатся в стандартном заголовочном файле "stdlib.h". (Имя malloc является сокращением от memory allocate - "захват памяти".) Прототипы этих функций выглядят следующим образом:

void *malloc(size_t n); // Захватить участок памяти

                       // размером в n байт

void free(void *p); // Освободить участок

                   // памяти с адресом p

Здесь n - это размер захватываемого участка в байтах, size_t - имя одного из целочисленных типов, определяющих максимальный размер захватываемого участка. Тип size_t задается в стандартном заголовочном файле "stdlib.h" с помощью оператора typedef (см. c. 117). Это обеспечивает независимость текста Си-программы от используемой архитектуры. В 32-разрядной архитектуре тип size_t определяется как беззнаковое целое число:

typedef unsigned int size_t;

Функция malloc возвращает адрес захваченного участка памяти или ноль в случае неудачи (когда нет свободного участка достаточно большого размера). Функция free освобождает участок памяти с заданным адресом. Для задания адреса используется указатель общего типа void*. После вызова функции malloc его необходимо привести к указателю на конкретный тип, используя операцию приведения типа. Например, в следующем примере захватывается участок динамической памяти размером в 4000 байтов, его адрес присваивается указателю на массив из 1000 целых чисел:

int *a;     // Указатель на массив целых чисел

. . .

a = (int *) malloc(1000 * sizeof(int));

Выражение в аргументе функции malloc равно 4000, поскольку размер целого числа sizeof(int) равен четырем байтам. Для преобразования указателя используется операция приведения типа (int *) от указателя обобщенного типа к указателю на целое число.

Еще раз

 
#include 
int main() 
{ 
double *ptd; 
ptd = (double *)malloc(10 * sizeof(double)); 
if(ptd != NULL) 
{ 
for(int i = 0;i < 10;i++) 
ptd[i] = i; 
}

else printf(“Не удалось выделить память.”); 
free(ptd); 
return 0; 
}

При вызове функции malloc() выполняется расчет необходимой области памяти для хранения 10 элементов типа double. Для этого используется функция sizeof(), которая возвращает число байт, необходимых для хранения одного элемента типа double. Затем ее значение умножается на 10 и в результате получается объем для 10 элементов типа double. В случаях, когда по каким-либо причинам не удается выделить указанный объем памяти, функция malloc() возвращает значение NULL. Данная константа определена в нескольких библиотеках, в том числе в и . Если функция malloc() возвратила указатель на выделенную область памяти, т.е. не равный NULL, то выполняется цикл, где записываются значения для каждого элемента. При выходе из программы вызывается функция free(), которая освобождает ранее выделенную память. Формально, программа написанная на языке С++ при завершении сама автоматически освобождает всю ранее выделенную память и функция free(), в данном случае, может быть опущена. Однако при составлении более сложных программ часто приходится много раз выделять и освобождать память. В этом случае функция free() играет большую роль, т.к. не освобожденная память не может быть повторно использована, что в результате приведет к неоправданным затратам ресурсов ЭВМ.

calloc

#include требуется только для объявления
функции

char *calloc(n,size);
unsigned n; количество элементов
unsigned size; длина каждого элемента в байтах
Описание

Функция calloc захватывает пространство для хранения массива из n элементов, каждый длиной size байт. Каждый элемент инициализируется в 0.

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

Функция calloc возвращает указатель char на захваченное пространство.
В памяти, на которую указывает возвращаемое значение, гарантировано выравнивание для хранения любого типа объекта. Чтобы получить указатель на тип, отличный от char, используется преобразователь типа возвращаемого значения.
Возвращается значение NULL, если осталось недостаточно памяти.

#include 
#include 
int main() 
{ 
double *ptd; 
ptd = (double *)сalloc(10,sizeof(double)); 
if(ptd != NULL) 
{ 
for(int i = 0;i < 10;i++) 
ptd[i] = i; 
}

else printf(“Не удалось выделить память.”); 
free(ptd); 
return 0; 
}

#include требуется только для объявления
функции

char *realloc(ptr,size);
char *ptr; указатель на ранее захваченный
блок памяти
unsigned size; новый размер в байтах

Описание.

Функция realloc изменяет размер ранее захваченного блока памяти.  Аргумент ptr указывает на начало блока. Аргумент size задает новый размер блока в байтах. Содержимое блока не изменяется. Аргумент ptr может указывать на блок, который должен быть освобожден прежде, чем последуют вызовы calloc, halloc, malloc,
realloc.

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

Функция realloc возвращает char-указатель на перезахваченный блок памяти. Блок может быть передвинут, если его размеры изменены, поэтому аргумент ptr для функции realloc не обязательно должен быть таким же, как и возвращаемое значение.
Возвращается значение NULL, если памяти недостаточно, чтобы расширить блок к заданному размеру. Если это происходит, то первоначальный блок освобождается.
В памяти, на которую указывает возвращаемое значение, гарантировано выравнивание для хранения любого типа объекта. Чтобы получить указатель на тип, отличный от char, используется преобразователь типа возвращаемого значения.

Пример:

#include 
#include 

char *alloc;

/* выбирает достаточно большое пространство для 50
символов */

alloc=malloc(50*sizeof(char));
.
.
.

/* перезахватывает блок, который содержит 100 символов */
if (alloc != NULL)
alloc=realoc (alloc,100*sizeof(char));

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

Память остаётся «занятой», даже если ни один указатель в программе на неё не ссылается (для освобождения памяти используется функция free()). Накопление «потерянных» участков памяти приводит к постепенной деградации системы. Ошибки, связанные с неосвобождением занятых участков памяти, называются утечками памяти 

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

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

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

Неудачная организация программы, в которой выделяется и освобождается множество небольших объёмов памяти — возможна фрагментация свободной памяти («пунктир»), при которой свободной памяти в сумме остаётся много, но выделить большой кусок невозможно.

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




1. Контрольная работа По курсу- Уголовный процесс
2. а стимулирует печень
3. Синкретизм
4. Заря10 к Львовой
5. это сердцевина каждого явления это то внутреннее что скрыто от внешнего созерцания
6. Борьба патрициев и плебеев в Древнем Риме
7. История зарубежной литературы II половина XX века
8. язык Friends in Your Life Friends re importnt in your life becuse you spend lot of time with them
9. Тема 6- Міжнародна міграція робочої сили
10. Реферат- Основные черты и особенности свободных (специальных) экономических зон
11. первых той ролью которую играют средства массовой информации печать телевидение радио в формировании мн
12. История развития межкультурной коммуникации в России
13. Раскройте скобки употребляя глаголы в Present Simple
14. Авраам и его история Фрагмент- [Быт
15. Десятку капитала бренда т
16. Статья- Зоны геолого-экологического риска тектонической природы и безопасность жизнедеятельности
17. ПОЯСНИТЕЛЬНАЯ ЗАПИСКА Рабочая программа курса Окружающий мир разработана на основе авторской прогр
18. Новая энциклопедия для мальчиков- Современная школа2; 2006 ISBN 9856751705 Аннотация Автор в форме доверите
19. Задание на курсовую работу Для студентов 4го курса заочной формы обучения
20. Лекция 13- Прибыль и рентабельность в строительстве