Ответ 1
Структура программы в памяти
Ниже приведена базовая структура любой программы при загрузке в память.
+--------------------------+
| |
| command line |
| arguments |
| (argc and argv[]) |
| |
+--------------------------+
| Stack |
| (grows-downwards) |
| |
| |
| |
| F R E E |
| S P A C E |
| |
| |
| |
| |
| (grows upwards) Heap |
+--------------------------+
| |
| Initialized data |
| segment |
| |
+--------------------------+
| |
| Initialized to |
| Zero (BSS) |
| |
+--------------------------+
| |
| Program Code |
| |
+--------------------------+
Несколько замечаний:
- Сегмент данных
- Инициализированный сегмент данных (инициализирован явным инициализатором программистами)
- Неинициализированный сегмент данных (инициализируется нулевым сегментом данных - BSS [Запуск блока с символом])
- Сегмент кода
- Области стека и кучи
Сегмент данных
Сегмент данных содержит глобальные и статические данные, которые явно инициализируются пользователями, содержащими инициализированные значения.
Другая часть сегмента данных называется BSS (из-за того, что старые системы IBM имели этот сегмент, инициализированный до нуля). Это часть памяти, где ОС инициализирует блок памяти нулями. Таким образом, неинициализированные глобальные данные и статические значения получают значение по умолчанию как ноль. Эта область фиксирована и имеет статический размер.
Область данных разделяется на две области на основе явной инициализации, поскольку переменные, которые должны быть инициализированы, могут быть инициализированы один за другим. Однако переменные, которые не инициализируются, не обязательно должны быть явно инициализированы с помощью 0 поочередно. Вместо этого задание инициализации переменной остается в ОС. Эта массовая инициализация может значительно сократить время, необходимое для загрузки исполняемого файла.
В основном макет сегмента данных находится в управлении базовой ОС, но некоторые загрузчики предоставляют частичный контроль пользователям. Эта информация может быть полезна в таких приложениях, как встроенные системы.
Эта область может быть адресована и доступна с помощью указателей из кода. Автоматические переменные имеют накладные расходы при инициализации переменных каждый раз, когда они требуются, и для выполнения этой инициализации требуется код. Однако переменные в области данных не имеют такой перегрузки во время выполнения, поскольку инициализация выполняется только один раз, а также при загрузке.
Сегмент кода
Программный код - это область кода, где исполняемый код доступен для выполнения. Эта область также имеет фиксированный размер. К ним можно обращаться только указатели на функции, а не другие указатели данных. Еще одна важная информация, которую следует отметить здесь, состоит в том, что система может рассматривать эту область как область памяти только для чтения, и любая попытка записи в этой области приводит к поведению undefined.
Постоянные строки могут быть помещены либо в код или область данных, и это зависит от реализации.
Попытка написать в область кода приводит к поведению undefined. Например (я приведу только примеры C
), следующий код может привести к ошибке во время выполнения или даже к сбою системы.
int main()
{
static int i;
strcpy((char *)main,"something");
printf("%s",main);
if(i++==0)
main();
}
Области стека и кучи
Для исполнения программа использует две основные части: стек и кучу. Фреймы стека создаются в стеке для функций и кучи для распределения динамической памяти. Стек и куча неинициализированы. Поэтому все, что бы там ни было в памяти, становится исходным (мусор) значением для объектов, созданных в этом пространстве.
Давайте посмотрим на примерную программу, чтобы показать, какие переменные будут храниться там, где
int initToZero1;
static float initToZero2;
FILE * initToZero3;
// all are stored in initialized to zero segment(BSS)
double intitialized1 = 20.0;
// stored in initialized data segment
int main()
{
size_t (*fp)(const char *) = strlen;
// fp is an auto variable that is allocated in stack
// but it points to code area where code of strlen() is stored
char *dynamic = (char *)malloc(100);
// dynamic memory allocation, done in heap
int stringLength;
// this is an auto variable that is allocated in stack
static int initToZero4;
// stored in BSS
static int initialized2 = 10;
// stored in initialized data segment
strcpy(dynamic,"something");
// function call, uses stack
stringLength = fp(dynamic);
// again a function call
}
Или рассмотрим еще более сложный пример,
// command line arguments may be stored in a separate area
int main(int numOfArgs, char *arguments[])
{
static int i;
// stored in BSS
int (*fp)(int,char **) = main;
// points to code segment
static char *str[] = {"thisFileName","arg1", "arg2",0};
// stored in initialized data segment
while(*arguments)
printf("\n %s",*arguments++);
if(!i++)
fp(3,str);
}
Надеюсь, это поможет!