前言
在学习Linux下C编程时, 我们了解到程序中的每一个变量都是在内存中有分布的.
程序占用的内存区域如下: 系统空间、命令行参数区、栈区、堆区、数据段、文本段.
linux下进程的内存布局
一般来说栈区的生长方向是从上往下的, 堆区的生长方向是从下往上.
但是对于不同的系统栈区的生长方向会有不一样的变化, 接下来我们一起验证
程序验证内存布局
程序源码
/*********************************************************************************
* Copyright: (C) 2021 guanyunpeng
* All rights reserved.
*
* Filename: memory_layout.c
* Description: This file
*
* Version: 1.0.0(2021年08月16日)
* Author: guanyunpeng <364521112@qq.com>
* ChangeLog: 1, Release initial version on "2021年07月30日 22时44分35秒"
*
********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
int g_val1;
int g_val2;
int g_val3 = 1;
int g_val4 = 2;
void local_variables(void)
{
int local_variables1;
int local_variables2;
printf("(栈区)local_variables1 的地址为: %p\n", &local_variables1);
printf("(栈区)local_variables2 的地址为: %p\n", &local_variables2);
}
int main (int argc, char **argv)
{
char *ptr1 = malloc(10);
char *ptr2 = malloc(10);
static int sta_val1 = 5;
static int sta_val2 = 6;
char *str1 = "hello";
char *str2 = "world";
local_variables();
printf("(堆区)ptr1 的地址为: %p\n", &ptr1);
printf("(堆区)ptr2 的地址为: %p\n", &ptr2);
printf("(.bss)g_val1 的地址为: %p\n", &g_val1);
printf("(.bss)g_val2 的地址为: %p\n", &g_val2);
printf("(.data)sta_val1 的地址为: %p\n", &sta_val1);
printf("(.data)sta_val2 的地址为: %p\n", &sta_val2);
printf("(.data)g_val3 的地址为: %p\n", &g_val3);
printf("(.data)g_val4 的地址为: %p\n", &g_val4);
printf("(.rodata)\"hello\" 的地址为: %p\n", str1);
printf("(.rodata)\"world\" 的地址为: %p\n", str2);
return 0;
}
运行结果
测试一
Linux系统版本信息如下:
运行结果:
我们可以清楚的看到各个变量的存储位置
这里可能有人要有疑问了, 比如俩个字符串的存放地址为什么是"hello"要比"world"低呢?
首先我们先定义的char *str1 = “hello”; 再定义的char *str2 = “world”; 所以在地址分布上是先存放的"hello", 再存放"world". 其他变量也是如此.
这里特别注意一下, 看栈区的变量
local_variables1是先定义的, 地址为: 0x7ed5042c
local_variables2是后定义的, 地址为: 0x7ed50428
由此可见, 此Linux系统下, 栈空间的生长方向是从上往下的.
测试二
Linux系统版本信息如下:
运行结果:
我们可以清楚的看到各个变量的存储位置
这里特别注意一下, 看栈区的变量
local_variables1是先定义的, 地址为: 0x7fffb2a75290
local_variables2是后定义的, 地址为: 0x7fffb2a75294
由此可见, 此Linux系统下, 栈空间的生长方向是从下往上的.
补充一个有关静态局部变量的问题
我们都知道静态局部变量存储在.data段的, 那么此时我们如果重复调用某个函数, 这个函数里面有一个静态局部变量, 程序是会每次调用的时候都给这个静态局部变量分配内存吗?还是只分配一次呢? 接下来我们通过程序来验证!
验证程序源码
#include <stdio.h>
int test ()
{
static int a;
a++;
printf("a,p:%p\n", &a);
printf("a:%d\n", a);
return 0;
}
int main (int argc, char **argv)
{
int i = 0;
for(i=0; i<3; i++)
{
printf("第%d次\n", i);
test();
}
return 0;
}
运行结果如下
我们通过运行结果可以看到, 多次调用函数, 并不会为函数中的静态局部变量多次分配内存.
这是因为静态局部变量只在定义它的函数内有效, 只是程序仅分配一次内存, 函数返回后, 该变量不会消失; 静态局部变量的生存期虽然为整个工程, 但是其作用仍与局部变量相同, 即只能在定义该变量的函数内使用该变量.