===================== 1.程序文件分析 ==========================
ELF:Linux系统下,可执行程序文件。(可重定位文件)
(类似于Windows中的exe)
程序文件中,需要特别关注的文件段:
备注:
file 文件名
readelf -S 程序名
===================== 2.进程内存布局 ==========================
浏览一下书本 《2.4 内存管理》章节
尝试找出以下问题的答案:
内核、栈、堆、数据段、代码段、不可访问区。
.init 系统初始化代码段
.text 用户代码段
.rodata 常量数据段(只读数据段)
.data 已初始化静态数据段
.bss 未初始化静态数据段
不变:数据段、代码段
变化:
用户代码、常量区、栈。
备注:
函数内部定义的变量,称为局部变量,位于栈空间
函数外部定义的变量,称为全局变量,位于静态数据段
int g_a=100; // .data 已初始化,则不做任何处理
char g_b; // .bss 未初始化,这块内存会被自动清零
(栈空间中的局部变量,如果未初始化,则为乱码数据(随机值)。)
修饰局部变量:将该局部变量置于静态数据段。
修饰全局变量、函数:将该变量或函数链接类型由外部链接类型修改为内部链接类型。
(如果全局变量、函数只在单个文件中使用,可以使用static修饰,避免出现重名冲突)
demo1_内存分布
#include<stdio.h>
// 函数外部定义的变量,称为全局变量,位于静态数据段
int g_a=100; // .data 不做任何处理
char g_b; // .bss 这块内存会被自动清零
// 子函数存储在.text用户代码
unsigned char func_sum(char a, float b) // 形参位于栈空间
{
// 168=65+3.5+100+0
return a+b+g_a+g_b; // 函数返回后,会将当前函数所有栈空间数据释放。(a, b)
}
// main主函数存储在.text用户代码
int main()
{
// 函数内部定义的变量,称为局部变量,位于栈空间
int n1=100; // n1位于栈空间,整型常量100位于常量区(只读区)
float n2=3.5; // n2位于栈空间,浮点型常量3.5位于常量区
char n3='A'; // n3位于栈空间,字符常量'A'位于常量区
char *str = "hello"; // str位于栈空间,字符串常量"hello"位于常量区
// str[0] = 'a'; // 尝试对常量区写入会导致出现段错误
printf("%c\n", *str); // 对常量区读取是允许。
printf("%ld %ld\n", sizeof('A'), sizeof(100));
// sum位于栈空间,跳转到用户代码中的func_sum的入口地址
unsigned char sum = func_sum(n3, n2);
printf("sum: %c(%d)\n", sum, sum);
return 0;
}
demo2_static
#include<stdio.h>
// 如需使用其他文件的函数,需要添加外部声明
extern void func_2(void);
// static:静态的
// int g_a = 200; // 未添加static,是外部链接类型
static int g_a = 200; // 添加static,修改为内部链接类型
void func_1(void)
{
// int a=100; // 局部变量
static int a=100; // static修饰的局部变量(只能被初始化1次)
a++;
printf("a(%p): %d\n", &a, a);
}
int main()
{
func_1();
func_1();
func_1();
func_1();
func_1();
func_2();
return 0;
}
demo3_另一个文件
#include<stdio.h>
// 如需要使用其他文件的变量,需添加外部声明
extern int g_a;
void func_2(void)
{
printf("g_a: %d\n", g_a);
}
demo4_堆空间使用
#include <stdio.h>
#include <stdlib.h>
// 申请堆空间
// #include <stdlib.h>
// void *malloc(size_t size); // 申请 size 字节的堆空间
// void *calloc(size_t nmemb, size_t size); // 申请 nmemb*size 字节的堆空间
// void *realloc(void *ptr, size_t size); // 重新申请一块size字节堆空间
// 释放堆空间
// void free(void *ptr); // 但不需要使用到该块内存时,释放空间。
// 使用场景:需要使用的内存较大,需要自行决定内存释放时机。
int main()
{
// 1M字节 = 1024K字节 = 1024*1024 字节
// char arr1[7*1024*1024] = {0};
// 位于栈空间,可使用指令(ulimit -a)查看,最大是8M
// 申请10M堆空间
// char *arr1 = malloc(10*1024*1024);
char *arr1 = calloc(10, 1024*1024);
// arr1[0] = 'A';
*(arr1+0) = 'A';
printf("%c\n", arr1[0]);
// 释放堆空间(当程序结束时,所有内存也会被释放。)
free(arr1);
return 0;
}